Unity:用泛型注册并解析 class

Unity: Register and resolve class with generic type

我正在使用 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();
    }
}

我知道使用容器作为服务定位器被认为是一种反模式,但我不知道有什么更好的方法来解决这个问题。如果有更好的模式来做这件事,我洗耳恭听……另一种方法是使用 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; }
}

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

这就是泛型寄存器的用途。一些 IOC 将该方法命名为 RegisterGeneric 以使其不言自明(例如 autofac),但统一保留它 just an overload of RegisterType.

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

另请注意,您的可注射物具有多个构造函数。 That itself is considered as anti-pattern.

如果你修复了多构造器问题,上面的注册就可以了。

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

如果您使用配置文件注册您的classes和接口,这可能会有所帮助.

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

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

在这里,我正在注册 class(TModel),我将使用我的通用接口(ICollectionWrapper) 和 Class(CollectionWrapper)。 然后我可以通过 DI

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

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