簡體   English   中英

無法使用 KeyFilterAttribute 無法解決 AutoFac Keyed 服務

[英]Unable to resolve AutoFac Keyed service with KeyFilterAttribute not working

我有一個通用的 UnitOfWork 模式實現,這些 UnitOfWork 對象依賴於我的服務類。 下面的片段應該可以幫助讀者理解我的代碼設置:

IUnitOfWork 接口

public interface IUnitOfWork<out TContext> where TContext : IDbContext

工作單元類

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")
        {

        }
    }

評論服務類:

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 屬性計算為 OpenStaarsDbContext 類型。 考慮到我們的注冊,這尤其奇怪。

在此處輸入圖片說明

如果我們通過在 OpenStaarsDbContext 之后注冊 GenevaDataDbContext 來重新排序我們的 IDbContext 注冊,這會變得更加奇怪。 現在 _dbContext 評估為 GenevaDataDbContext 實例。

如何解決此問題以使 CommentsService 的 reconciliationUoW 依賴項具有 ReconciliationDbContext 的正確實例?

這種行為的原因是你將IDbContext注入到你的UnitOfWork構造函數中,而不是TContext - 容器只是忽略你在注冊中作為通用參數提供的類型,並采用它在容器中找到的第一個IDbContext - 這將是上次注冊,無論您使用什么密鑰。

為了使其工作,而不是使用鍵控注冊,您可以簡單地注入IUnitOfWork<ContextYouNeed>而不是IUnitOfWork<IDbContext> - 它也會簡化代碼。 首先你需要修復你的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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM