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