smoksnes smoksnes -4 years ago 236
C# Question

Unity: Register and resolve class with generic type

I'm using Unity and try to follow to SOLID-principles as far as possible. Therefore all implementations only have dependencies to interfaces.

I have a collectionwrapper which looks like this:

public interface ICollectionWrapper<TModel>
{
int TotalCount { get; set; }
IEnumerable<TModel> Items { get; set; }
}


Now I want to create the instance of
ICollectionFactory<T>
with a factory. This is what I got so far:

public interface ICollectionWrapperFactory
{
ICollectionWrapper<T> CreateCollection<T>();
ICollectionWrapper<T> CreateCollection<T>(IEnumerable<T> items);
ICollectionWrapper<T> CreateCollection<T>(IEnumerable<T> items, int totalCount);
}

public class CollectionWrapperFactory : ICollectionWrapperFactory
{
private readonly IUnityContainer _container;

public CollectionWrapperFactory(IUnityContainer container)
{
_container = container;
}

public ICollectionWrapper<T> CreateCollection<T>()
{
var collectionWrapper = _container.Resolve<ICollectionWrapper<T>>();
return collectionWrapper;
}

public ICollectionWrapper<T> CreateCollection<T>(IEnumerable<T> items)
{
throw new System.NotImplementedException();
}

public ICollectionWrapper<T> CreateCollection<T>(IEnumerable<T> items, int totalCount)
{
throw new System.NotImplementedException();
}
}


I know that using the container as a servicelocator is considered an anti-pattern, but I don't know any better way to solve this. If there's a better pattern for doing this I'm all ears... An alternative is using the Activator, but then the factory would need to know about the actual implementation of
ICollectionWrapper<T>
.

But the real problem is that I cannot register the ICollectionWrapper correctly.

container.RegisterType<ICollectionWrapper<T>, CollectionWrapper<T>>(new TransientLifetimeManager()); // Does not compile.


T
may be any type. I want to be able to create instances of
ICollectionWrapper<T>
without having to register every possible combination of
T
.


Currently I only have one implementation of
ICollectionWrapper<T>
. But the point is that I really want Unity to be the only part that knows about the actual implementation.

[DataContract]
public class CollectionWrapper<TModel> : ICollectionWrapper<TModel>
{
public CollectionWrapper(IEnumerable<TModel> items)
{
Items = items;
}

public CollectionWrapper(IEnumerable<TModel> items, int totalCount)
{
Items = items;
TotalCount = totalCount;
}

public CollectionWrapper()
{

}

[DataMember]
public int TotalCount { get; set; }
[DataMember]
public IEnumerable<TModel> Items { get; set; }
}

Answer Source

T may be any type. I want to be able to create instances of ICollectionWrapper without having to register every possible combination of T.

That's what register generics is for. Some IOC name the method as RegisterGeneric to make it self explanatory (autofac for example), but unity keep it just an overload of RegisterType.

container.RegisterType(typeof(ICollectionWrapper<>), typeof(CollectionWrapper<>), new TransientLifetimeManager());

Also note that your injectable is having multiple constructors. That itself is considered as anti-pattern.

If you fix the multiple construtor thing, above registration will work.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download