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

本文关键字:和解 注册 泛型类型 Unity | 更新日期: 2023-09-27 18:34:06

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

我有一个集合包装器,看起来像这样:

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

我知道使用容器作为服务定位器被认为是一种反模式,但我不知道有什么更好的方法来解决这个问题。如果有更好的模式来做到这一点,我全听...另一种方法是使用激活器,但随后工厂需要了解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; }
}

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

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

这就是寄存器泛型的用途。一些 IOC 将该方法命名为 RegisterGeneric 以使其不言自明(例如 autofac(,但 unity 仅将其保留为RegisterType的重载。

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

另请注意,您的注射对象具有多个构造函数。这本身被认为是反模式的。

如果您修复了多个构造器问题,则上述注册将起作用。

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

使用配置文件注册类和接口,这可能会有所帮助。

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

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

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