无法使用Unity将List <t>的依赖项作为构造函数参数注入

时间:2015-05-18 22:25:16

标签: c# unity-container

我正在使用Unity来实例化我的MenuRepository实例。尝试这样做时,我收到以下错误。

  

类型列表`1有多个长度为1的构造函数。无法消除歧义。

我已尝试过以下注册,但没有运气..

container.RegisterType<IMenuRepository, MenuRepository>(
    new PerThreadLifetimeManager(), 
    new InjectionConstructor(typeof(IMonopolyEntitiesDbContext), 
    typeof(List<MenuLink>)));

这是我的注册

container.RegisterType<MenuLink>();
container.RegisterType <List<MenuLink>>();
container.RegisterType<IMonopolyEntitiesDbContext, MonopolyEntities>(
    new PerThreadLifetimeManager());
container.RegisterType<IMenuRepository, MenuRepository>(
    new PerThreadLifetimeManager(), 
    new InjectionConstructor(typeof(IMonopolyEntitiesDbContext), typeof(List<MenuLink>)));

MenuRepository

public class MenuRepository : IMenuRepository
{
    IMonopolyEntitiesDbContext _dbContext;
    List<MenuLink> _allsubMenus;

    public MenuRepository(IMonopolyEntitiesDbContext context, List<MenuLink> allsubMenus)
    {
        _dbContext = context;
        _allsubMenus = allsubMenus;
    }
}

2 个答案:

答案 0 :(得分:3)

我使用了没有参数的InjectionConstructor。

using (var c = new UnityContainer())
{
    c.RegisterType(typeof(List<string>), new InjectionConstructor());
    c.RegisterType<IMyParamClass, MyParamClass>();

    c.RegisterType<IMyClass, MyClass>(
                    new PerThreadLifetimeManager(),
                    new InjectionConstructor(typeof(IMyParamClass),
                    typeof(List<string>)));

    var obj = c.Resolve<IMyClass>();
    obj.write();
}

答案 1 :(得分:3)

您需要了解IoC容器的目标是将抽象映射到实现并从中构建对象图。因此,为了能够创建对象,Unity需要知道如何创建对象。但是,List<T>不是您的典型服务类型。它有多个构造函数,因此Unity没有关于如何创建此类型的线索。

但即使它确实知道如何创建它(例如通过使用List<T>的默认构造函数),这对你来说仍然没用,因为在这种情况下会向消费者注入一个空列表。这完全没有用。

所以你应该做的最少的事情就是确定要注入的内容。例如,通过这样做:

container.RegisterInstance<List<MenuLink>>(new List<MenuLink>
{
    new MenuLink { Id = 1, Name = "foo" },
    new MenuLink { Id = 2, Name = "bar" },
    new MenuLink { Id = 3, Name = "foobar" },
});

这对您有用,因为您声明List<MenuLink>实际上是一个单身,并且没有从数据库中填充。但是,在容器中注册此List<MenuLink>仍然会有问题,因为现在可以将List<T>注入任何消费者,而您永远不应该这样做。此List<MenuLink>MenuRepository的实现细节,可能负责更新它。将List<MenuLink>注入其他使用者是有风险的,因为List<T>不是线程安全的。最好将此List<T>保留在MenuRepository内部,以便正确锁定。

因此,不是在容器中注册List<MenuLink>,而是使用列表明确注册存储库,如下所示:

var menuLinks = new List<MenuLink>
{
    new MenuLink { Id = 1, Name = "foo" },
    new MenuLink { Id = 2, Name = "bar" },
    new MenuLink { Id = 3, Name = "foobar" },
};

container.RegisterType<IMenuRepository, MenuRepository>(
    new PerThreadLifetimeManager(), 
    new ParameterOverride("allsubMenus", menuLinks));