Unity Hierarchy构造函数注入

时间:2014-06-13 15:28:41

标签: c# unity-container

我很难理解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>();
        }
    }
}

我怀疑我的问题是我不完全理解分层引用是如何解决的,而我的错误是显而易见的,但我仍然在学习,所以会很感激一些指针

1 个答案:

答案 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")))

您可以注意到,我更改了您提供IDataContextAsyncIUnitOfWorkAsync的顺序。基本上你的方式,你提供的参数顺序错误。


作为旁注,您不需要为每次注册提供名称。您只需要在同一个界面上多次注册时提供一个名称,即使在这种情况下,您仍然可以使用默认的未命名注册。

此外,您不需要手动告诉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有一个构造函数,它接受IDataContextAsyncIUnitOfWorkAsync,并为他们提供实例,因为他知道如何解决它们。这些接口的默认注册将被解析为类Zeus的实例(带有构造函数参数Zeus,可能是连接字符串?)和UnitOfWork

希望有所帮助!