Unity:使用泛型

时间:2016-02-11 08:29:24

标签: c# inversion-of-control unity-container factory-pattern

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

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

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

现在我想用工厂创建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();
    }
}

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

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

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

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

3 个答案:

答案 0 :(得分:13)

  

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

这就是注册泛型的用途。一些IOC将方法命名为RegisterGeneric以使其自我解释(例如autofac),但是统一保留just an overload of RegisterType

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

另请注意,您的注射剂具有多个构建器。 That itself is considered as anti-pattern

如果你修复了多个construtor的事情,上面的注册就可以了。

答案 1 :(得分:0)

public static void RegisterTypes(IUnityContainer container)
{
   container.RegisterType(typeof(IEmployee<>), typeof(Employee<>), new TransientLifetimeManager());
}

答案 2 :(得分:0)

如果您使用配置文件注册您的类和界面,这会有所帮助。

<alias alias="TModel" type="{namespace}.TModel, {assemblyname}" />

<register type="{namespace}.ICollectionWrapper[TModel], {assemblyname}" 
                mapTo="{namespace}.CollectionWrapper, {assemblyname}">
</register>

在这里,我正在注册要与我的通用接口( ICollectionWrapper )和类( CollectionWrapper 一起使用的类( TModel ) >)。 然后我可以通过DI来解决它

    public class MyClass
        {
            private readonly ICollectionWrapper<TModel> _collectionWrapper;

                public MyClass(ICollectionWrapper<TModel> collectionWrapper)
                {
                            _collectionWrapper= collectionWrapper;
                }
        }