Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
278 views
in Technique[技术] by (71.8m points)

c# - 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; }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...