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