我正在尝试利用Generics和MEF解决方案的优势,但是我正在努力让事情得到注册。 (使用MEF 2,.Net 4.51)。
以下是我想要使用的类和接口的简化版本:
public interface IAnimal
{
string Speak();
}
public interface IAnimalCatcher<T> where T : IAnimal
{
string WhatICatch();
T AnimalCaught { get; set; }
}
[Export(typeof(IAnimal))]
public class Dog : IAnimal
{
public string Speak()
{
return "Woof";
}
}
//[Export(typeof(IAnimalCatcher<IAnimal>))]
//[Export(typeof(IAnimalCatcher<Dog>))]
public class DogCatcher: IAnimalCatcher<Dog>
{
public string WhatICatch()
{
return "Dogs";
}
public Dog AnimalCaught { get; set; }
}
和执行组成的代码:
public class Program
{
private CompositionContainer _container;
[Import(typeof(IAnimal))]
public IAnimal TheAnimal;
[Import(typeof(IAnimalCatcher<>))]
public IAnimalCatcher<IAnimal> TheAnimalCatcher;
public Program()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
_container = new CompositionContainer(catalog);
this._container.ComposeParts(this);
}
}
我无法正确导出和导入Dog Class。我尝试了几种没有成功的组合(在课程上面评论过)。
错误如下:
System.ComponentModel.Composition.ChangeRejectedException是 未处理的消息=组成保持不变。变化 由于以下错误被拒绝:组成 产生了单一的构图错误。根本原因如下。 查看CompositionException.Errors属性以获取更详细的信息 信息。
1)没有找到符合约束条件的导出: ContractName MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal) RequiredTypeIdentity MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)
导致:无法设置导入'MEFGeneric.Program.TheAnimalCatcher(ContractName =“MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)”)'on 部分'MEFGeneric.Program'。元件: MEFGeneric.Program.TheAnimalCatcher (ContractName =“MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)”) - &gt; MEFGeneric.Program
请注意,IAnimalCatcher<IAnimal>
会注册,但这不会让我限制狗捕手。
有没有办法通过导入解决这个问题,或者我的设计存在缺陷,我是否应该以不同的方式实施DogCatcher?
答案 0 :(得分:2)
MEF正在寻找导出IAnimalCatcher<IAnimal>
的类型。您DogCatcher
导出IAnimalCatcher<Dog>
,因此不适合候选人。将DogCatcher
的导出更改为IAnimalCatcher<IAnimal>
不是解决方案,因为您无法将IAnimalCatcher<Dog>
分配给IAnimalCatcher<IAnimal>
。
如果您能够进行分配,则可以通过设置AnimalCaught
类型的DogCatcher
属性的值,将Cat
IAnimalCatcher.AnimalCaught
分配给IAnimal
}。您不希望DogCatcher
捕获Cat
,因此编译器将不允许它。
解决方案是更改DogCatcher
,使其实现IAnimalCatcher<IAnimal>
而不是IAnimalCatcher<Dog>
:
[Export(typeof(IAnimalCatcher<IAnimal>))]
public class DogCatcher: IAnimalCatcher<IAnimal>
{
public string WhatICatch()
{
return "Dogs";
}
public IAnimal AnimalCaught { get; set; }
}
这种不幸的副作用是你现在允许任何人修改DogCatcher
抓住的动物来说Cat
。
但还有另一种选择。如果您可以从AnimalCaught
移除设置器,则可以使IAnimal
类型参数协变(out
修饰符):
public interface IAnimalCatcher<out T> where T : IAnimal
{
string WhatICatch();
T AnimalCaught { get; }
}
这使得IAnimalCatcher<Dog>
到IAnimalCatcher<IAnimal>
的分配合法:
[Export(typeof(IAnimalCatcher<IAnimal>))]
public class DogCatcher: IAnimalCatcher<Dog>
{
public string WhatICatch()
{
return "Dogs";
}
public Dog AnimalCaught { get; private set; }
}