Unity:使用泛型类型注册和解析类

smo*_*nes 6 c# inversion-of-control unity-container factory-pattern

我正在使用Unity并尝试尽可能遵循SOLID原则.因此,所有实现仅具有接口的依赖性.

我有一个collectionwrapper,看起来像这样:

public interface ICollectionWrapper<TModel>
{
    int TotalCount { get; set; }
    IEnumerable<TModel> Items { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在我想创建ICollectionFactory<T>一个带工厂的实例.这是我到目前为止所得到的:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道使用容器作为servicelocator被认为是反模式,但我不知道有任何更好的方法来解决这个问题.如果有一个更好的模式来做到这一点我都是耳朵......另一种方法是使用Activator,但是工厂需要知道实际的实现ICollectionWrapper<T>.

但真正的问题是我无法正确注册ICollectionWrapper.

container.RegisterType<ICollectionWrapper<T>, CollectionWrapper<T>>(new TransientLifetimeManager()); // Does not compile.
Run Code Online (Sandbox Code Playgroud)

T可以是任何类型.我希望能够创建实例,ICollectionWrapper<T>而无需注册每个可能的组合T.

目前我只有一个实现ICollectionWrapper<T>.但重点是我真的希望Unity成为了解实际实现的唯一部分.

[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; }
}
Run Code Online (Sandbox Code Playgroud)

Sri*_*vel 16

T可以是任何类型.我希望能够创建ICollectionWrapper的实例,而无需注册T的每个可能的组合.

这就是注册泛型的用途.一些IOC将该方法命名为RegisterGeneric使其自我解释(例如autofac),但是unity保持它只是一个重载RegisterType.

container.RegisterType(typeof(ICollectionWrapper<>), typeof(CollectionWrapper<>), new TransientLifetimeManager());
Run Code Online (Sandbox Code Playgroud)

另请注意,您的注射剂具有多个构建器.这本身被视为反模式.

如果你修复了多个construtor的事情,上面的注册将会起作用.