我有一个实现不同类的接口“ IItemsChanger”。
public interface IItemsChanger
{
void Change(int value)
}
一个可能的实现是一个简单的类,该类接收可能不同的item对象:
public class MyItemChanger : IItemChanger
{
private readonly IEnumerable<MyItem> _items;
public ArticoliStateChanger(IEnumerable<MyItem> items)
{
_items = items;
}
public void Change(int value)
{
...
}
}
如您所见,构造函数的IEnumerable为MyItem;在另一个实现中,可以将MyItem替换为另一个IEnumerable。
我想在实现中通过构造函数注入MyItem的列表,因此我需要建立一个工厂。 由于项目可以采用不同的类型,因此我还需要保持工厂为通用类型,例如:
public interface IItemsChangerFactory<T>
{
IItemsChanger Create(IEnumerable<T> items);
}
如果这有道理,我就这样配置Ninject:
Bind(typeof(IItemsChangerFactory<>)).ToFactory();
Bind<IItemsChanger>().To<MyItemChanger>();
当我尝试获得这样的实现时:
var kernel = new StandardKernel(new MyModule());
var k = kernel.Get<IItemsChangerFactory<MyItem>>();
我得到一个错误:
“无法将类型为“ Castle.Proxies.ObjectProxy”的对象转换为类型为“ MyNamespace.IItemsChangerFactory`1 [MyItem]”
如何解决?
答案 0 :(得分:0)
Ninject或Ninject.Extensions.Factory都不支持此问题。
问题在于Ninject或工厂都不知道如何将T
的{{1}} Type参数映射到特定的IItemsChangerFactory<T>
实现。该逻辑需要由您编写。
现在是下一个问题。您不能具有接口类型构造函数,即您不能声明IItemsChanger
的构造函数来实现MyItemChanger
。您可以编写为编译时安全的代码,但需要一些样板代码,即:
IItemsChangerFactory<MyItem>
或者您可以使用反射-但会丢失编译时间检查:
class MyItemChangerFactory : IItemsChangerFactory<MyItem>
{
public IItemsChanger Create(IEnumerable<T> items)
{
return new MyItemChanger(items);
}
}
当然可以用以下方式代替class ItemChangerFactory<TItem, TChanger> : IItemsChangerFactory<TItem>
{
public IItemsChanger Create(IEnumerable<T> items)
{
return Activator.CreateInstance(typeof(TChanger), new object[] { items });
}
}
:n Activator