[英]Unable to resolve keyed generic parameter of registered type using Autofac
[英]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.