首页 > 解决方案 > 在 AutoFac 中使用带有参数的 lambda 表达式注册通用类型

问题描述

我正在尝试这样做但是使用了一个通用类,例如:

public class BaseRepository<TEntity> : IBaseRepository<TEntity>, IDisposable
    where TEntity : class, new()
    {
        public BaseRepository(IIndex<ContextKey, IDbContextBase> factory, ContextKey key)
        {
            Context = factory[key];
            Set = Context.Set<TEntity>();
        }
}

这样我就可以将ContextKey密钥作为参数传递。

我正在尝试根据已传递给BaseRepository<>类的 ctor 的密钥动态解析 dbcontext。

像这样注册它:

builder.Register((c, p) =>
                 new BaseRepository<>(p.Named<ContextKey>("key")))
       .As<IBaseRepository<>>();

像这样解决

var reader = scope.Resolve<IBaseRepository<ActionEntity>>(
new NamedParameter("key", ContextKey.Applications));

传递的密钥是:

public enum ContextKey
{
    Pure, Phoebus, Applications, Legacy, None
}

并且该factory参数内置在 Autofac 中 - 它由 Autofac 自动注入和处理。

标签: c#dependency-injection.net-coreautofac

解决方案


IIndex<ContextKey, IDbContextBase> factory, ContextKey key存储库构造函数中拥有看起来很像可以委托给组合根的实现问题。

我将首先简化存储库的构造函数以遵循显式依赖原则。

public class BaseRepository<TEntity> : IBaseRepository<TEntity>, IDisposable
    where TEntity : class, new() {

    //...

    public BaseRepository(IDbContextBase context) {
        Context = context;
        Set = Context.Set<TEntity>();
    }

    //...
}

然后,Composition Root 将负责确保正确构建存储库。

ContextKey key = //known value

//...Assumes IIndex<ContextKey, IDbContextBase> factory is registered

builder
    .RegisterGeneric(typeof(BaseRepository<>))
    .As(typeof(IBaseRepository<>))
    .WithParameter(
        new ResolvedParameter(
            (pi, ctx) => pi.ParameterType == typeof(IDbContextBase) && pi.Name == "context",
            (pi, ctx) => {
                var factory = ctx.Resolve<IIndex<ContextKey, IDbContextBase>>();
                return factory[key];
            })
    );

//...

var container = builder.Build();

注意使用ResolvedParameter动态获取要注入存储库的参数。


推荐阅读