0
votes

I'm using Unity to instantiate my MenuRepository instance. I'm getting the following error when trying to do so..

The type list`1 has multiple constructors of length 1. unable to disambiguate.

I've tried the following registration, but with no luck..

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

Here's my registration

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
List has multiple constructors. Unity can’t find out which should get used…you need to provide more information to unity. But I would recommend you creating a service which creates the list and inject this service into your repository.musium
Exactly so, Unity needs to know whether you mean List<T>(sequence) or List<T>(length).neontapir
What does List<MenuLink> contain? Is this a fixed list of MenuItem objects that doesn't change for the duration of the application? Or is this data that is requeried from the database on each request? Could you elaborate?Steven
Hi ray abu, I've written a quite lengthy answer for you. I haven't posted it yet though, because I'm missing a some essential information to be able to answer this question. If you can answer my previous question about List<MenuLink>, it allows me to post my answer and help you with your problem.Steven
Sorry for late reply. List<MenuItem> menuItem object's state wouldn't change during the application and a singleton, but the collection can change. MenuItem object will hold data called from a datastore. I have resolve this issue now, will post my answer soon.ray abu

2 Answers

4
votes

You need to understand that the goal of an IoC container is to map abstractions to implementations and to build up object graphs from that. So to be able to create objects, Unity needs to know how to create objects. List<T> however, is not your typical service type. It has multiple constructors and Unity has therefore no clue of how to create this type.

But even if it did know how to create it (for instance by using the default constructor of List<T>), this still would be rather useless to you, because in that case an empty list would be injected into consumers. That's hardly ever useful, at all.

So the least you should do is exactly specify what to inject. For instance by doing this:

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" },
});

This will work for you, since you stated that the List<MenuLink> is practically a singleton and is not populated from the database. However, registering this List<MenuLink> in your container would still be problematic, because this List<T> can now be injected into any consumer, while you should never do this. This List<MenuLink> is an implementation detail of the MenuRepository that is probably responsible of updating it. Injecting the List<MenuLink> into other consumers is risky, because List<T> is not thread-safe. It's best to keep this List<T> internal to the MenuRepository, so it can do the proper locking.

So instead of registering the List<MenuLink> in the container, register the repository with the list explicitly as follows:

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));
3
votes

I used InjectionConstructor with no parameters.

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();
}

.