我正在使用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; }
}
答案 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;
}
}