我很难理解Unity如何解析层次结构树中对象的引用以及如何注入相关的构造函数。
目前我配置了我的容器:
container
.RegisterType<IDataContextAsync, Zeus>("ZeusLive", new PerRequestLifetimeManager(), new InjectionConstructor("ZeusLive"))
.RegisterType<IDataContextAsync, Zeus>("Zeus", new PerRequestLifetimeManager(), new InjectionConstructor("Zeus"))
.RegisterType<IUnitOfWorkAsync, UnitOfWork>("ZeusUnitOfWork", new InjectionConstructor(new ResolvedParameter<IDataContextAsync>("Zeus")))
.RegisterType<IRepositoryAsync<cd_Job>, Repository<cd_Job>>(new InjectionConstructor(new ResolvedParameter<IUnitOfWorkAsync>("ZeusUnitOfWork"), new ResolvedParameter<IDataContextAsync>("Zeus")));
(我使用的是通用的工作单元和存储库模式(https://genericunitofworkandrepositories.codeplex.com/))
问题在于这一行:
.RegisterType<IRepositoryAsync<cd_Job>, Repository<cd_Job>>(new InjectionConstructor(new ResolvedParameter<IUnitOfWorkAsync>("ZeusUnitOfWork"), new ResolvedParameter<IDataContextAsync>("Zeus")))
我收到以下错误:
The type Repository.Pattern.Ef6.Repository`1[[DataRepository.Models.cd_Job, DataRepository, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] does not have a constructor that takes the parameters (IUnitOfWorkAsync, IDataContextAsync)
Repository类的构造函数如下:
public Repository(IDataContextAsync context, IUnitOfWorkAsync unitOfWork)
{
_context = context;
_unitOfWork = unitOfWork;
// Temporarily for FakeDbContext, Unit Test and Fakes
var dbContext = context as DbContext;
if (dbContext != null)
{
_dbSet = dbContext.Set<TEntity>();
}
else
{
var fakeContext = context as FakeDbContext;
if (fakeContext != null)
{
_dbSet = fakeContext.Set<TEntity>();
}
}
}
我怀疑我的问题是我不完全理解分层引用是如何解决的,而我的错误是显而易见的,但我仍然在学习,所以会很感激一些指针
答案 0 :(得分:3)
您需要按照构造函数中定义的相同顺序提供InjectionConstructor
的参数。
您的构造函数定义如下:
public Repository(IDataContextAsync context, IUnitOfWorkAsync unitOfWork)
{
}
所以你需要像这样注册:
.RegisterType<IRepositoryAsync<cd_Job>, Repository<cd_Job>>(
new InjectionConstructor(
new ResolvedParameter<IDataContextAsync>("Zeus"),
new ResolvedParameter<IUnitOfWorkAsync>("ZeusUnitOfWork")))
您可以注意到,我更改了您提供IDataContextAsync
和IUnitOfWorkAsync
的顺序。基本上你的方式,你提供的参数顺序错误。
作为旁注,您不需要为每次注册提供名称。您只需要在同一个界面上多次注册时提供一个名称,即使在这种情况下,您仍然可以使用默认的未命名注册。
此外,您不需要手动告诉Unity如何解析每个构造函数参数,因为默认情况下他足够智能解析它(如果它知道如何解决它)。
所以你的例子可以简化为:
container
.RegisterType<IDataContextAsync, Zeus>("ZeusLive", new PerRequestLifetimeManager(), new InjectionConstructor("ZeusLive"))
.RegisterType<IDataContextAsync, Zeus>(new PerRequestLifetimeManager(), new InjectionConstructor("Zeus"))
.RegisterType<IUnitOfWorkAsync, UnitOfWork>()
.RegisterType<IRepositoryAsync<cd_Job>, Repository<cd_Job>>();
Unity非常聪明,意识到Repository
有一个构造函数,它接受IDataContextAsync
和IUnitOfWorkAsync
,并为他们提供实例,因为他知道如何解决它们。这些接口的默认注册将被解析为类Zeus
的实例(带有构造函数参数Zeus,可能是连接字符串?)和UnitOfWork
。
希望有所帮助!