【问题标题】:Unable to resolve AutoFac Keyed service with KeyFilterAttribute not working无法使用 KeyFilterAttribute 解决 AutoFac 键控服务不起作用
【发布时间】:2018-10-22 11:52:47
【问题描述】:

我有一个通用的 UnitOfWork 模式实现,这些 UnitOfWork 对象是我的服务类的依赖项。下面的 sn-ps 应该可以帮助读者理解我的代码设置:

IUnitOfWork 接口

public interface IUnitOfWork<out TContext> where TContext : IDbContext

UnitOfWork 类

public sealed class UnitOfWork<TContext> : IDisposable, IUnitOfWork<IDbContext> where TContext : IDbContext
    {
        private static readonly ILog Log = LogManager.GetLogger(typeof(UnitOfWork<TContext>));

        private readonly IDbContext _dbContext;
        private Dictionary<string, IRepository> _repositories;
        private IDbTransaction Transaction { get; set; }

        public UnitOfWork(IDbContext context)
        {
            _dbContext = context;
        }
    }

容器注册:

builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>));

builder.RegisterType<ReconciliationDbContext>().As<IDbContext>();
builder.RegisterType<GenevaDataDbContext>().As<IDbContext>();
builder.RegisterType<OpenStaarsDbContext>().As<IDbContext>();

builder.RegisterType<UnitOfWork<ReconciliationDbContext>>().Keyed<IUnitOfWork<IDbContext>>(ContextKey.Recon);
builder.RegisterType<UnitOfWork<OpenStaarsDbContext>>().Keyed<IUnitOfWork<IDbContext>>(ContextKey.OpenStaars);

builder.RegisterType<CommentsService>().As<ICommentsService>().WithAttributeFiltering();

DbContext 类:

public class ReconciliationDbContext : BaseDbContext<ReconciliationDbContext>, IDbContext
    {
        private const string DbSchema = "BoxedPosition";

        public ReconciliationDbContext() : base("Reconciliation")
        {

        }
    }

public class OpenStaarsDbContext : BaseDbContext<OpenStaarsDbContext>, IDbContext
    {
        public OpenStaarsDbContext() : base("OpenStaars")
        {

        }
    }

CommentsService 类:

public class CommentsService : ICommentsService
    {
        private readonly IUnitOfWork<IDbContext> _reconciliationUoW;

        public CommentsService([KeyFilter(ContextKey.Recon)] IUnitOfWork<IDbContext> reconciliationUoW)
        {
            _reconciliationUoW = reconciliationUoW;
        }
    }

解决 ICommentsService:

var commentsService = container.Resolve<ICommentsService>();

现在,当我尝试解析 ICommentsService 类型时,它会实例化 UnitOfWork 依赖项。但是,UnitOfWork._dbContext 属性的计算结果为 OpenStarsDbContext 类型。考虑到我们的注册情况,这尤其奇怪。

如果我们通过在 OpenStarsDbContext 之后注册 GenevaDataDbContext 来重新排序我们的 IDbContext 注册,那就更奇怪了。现在 _dbContext 评估为 GenevaDataDbContext 实例。

如何解决此问题,以使 CommentsService 的和解UoW 依赖项具有正确的 ReconciliationDbContext 实例?

【问题讨论】:

    标签: c# dependency-injection inversion-of-control autofac


    【解决方案1】:

    这种行为的原因是您将 IDbContext 注入到您的 UnitOfWork 构造函数中,而不是 TContext - 容器只是忽略您在注册时作为通用参数提供的类型并采用第一个 @987654325 @ 它在容器中找到 - 这将是最后一次注册,无论您使用什么键。

    为了使其工作,您可以简单地注入IUnitOfWork&lt;ContextYouNeed&gt; 而不是IUnitOfWork&lt;IDbContext&gt;,而不是使用键控注册——它也可以简化代码。首先你需要修复你的UnitOfWork 类:

    class UnitOfWork<TContext> : IUnitOfWork<TContext> where TContext : IDbContext
    {
        private readonly TContext _context;
    
        public UnitOfWork(TContext context)
        {
            _context = context;
        }
    }
    

    在您的注册中,您不需要注册特定的工作单元类型,标准的通用注册就足够了。但是您还需要注册您的上下文类型 AsSelf,以便 Autofac 会为您的工作单元实例正确注入它:

    builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>));
    
    builder.RegisterType<ReconciliationContext>().As<IContext>().AsSelf();
    builder.RegisterType<OpenStaarsContext>().As<IContext>().AsSelf();
    

    稍后,只需在您的服务中注入适当的工作单元:

    public CommentsService(IUnitOfWork<ReconciliationContext> reconciliationUoW)
    

    【讨论】:

    • 好吧,在 CommentsService 构造函数中将实际上下文指定为 IUnitOfWork 的通用参数会导致硬编码依赖并阻止我们模拟依赖,不是吗?如果我错了,请在这里纠正我。
    • 恕我直言,它不会 - 你可以模拟 IUnitOfWork&lt;AnyContext&gt;。与上下文接口的方式相同。
    • 我稍微修改了我的代码,因为我觉得IUnitOfWork接口上的TContext参数没有使用(参数没有被使用)。关于如何确保将正确的 DbContext 注入 UnitOfWork 类构造函数的问题仍然存在。我在同一问题上发布了另一个问题。请看一看。我很想得到使用键控过滤器属性的解决方案。 stackoverflow.com/questions/52947930/…
    • 我接受你的回答,尽管我通过使用非通用 IUnitOfWork 依赖项让它工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 2012-11-22
    相关资源
    最近更新 更多