我具有以下要使用MEF导出和导出的类接口模式:

public interface IDinosaur
{
    string Species { get; }
}

public class Pterodactyl : IDinosaur
{
    public string Species { get; set; }
    public float WingSpan { get; set; }
}

public interface ICage<in T>
{
    void Transport(T animal);
}

[Export(typeof(ICage<IDinosaur>))] // <-- This appears a problem
public class PterodactylCage : ICage<Pterodactyl>
{
    public void Transport(Pterodactyl dinosaur) { }
}

public class DinoTransportationService
{
    [Import(AllowDefault = true)]
    private ICage<IDinosaur> m_dinosaurCage = null;
}


现在我要说这是合法的,因为[Export(typeof(ICage<IDinosaur>))]确实输出了ICageIDinosaur(碰巧是Pterodactyl,但这实现了恐龙接口,所以应该没事吧?)。但是,这给了我CompositionException。说:

"The export 'PterodactylCage (ContractName=\"ICage(IDinosaur)\")' is not assignable to type 'ICage`1[[IDinosaur, MyProgramme, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'."


我可以通过将导出更改为:

[Export(typeof(ICage<Pterodactyl>))] // <-- This is ok
public class PterodactylCage : ICage<Pterodactyl>


并导入到:

[Import(AllowDefault = true)]
private ICage<Pterodactyl> m_dinosaurCage = null;


除此之外,现在的导入变得太具体了,实际上,就我而言,导入是在另一个从未听说过翼手龙的程序集中进行的,因此这是一个不好的解决方案。
为什么第一个示例不合法,该模式的解决方案是什么?

最佳答案

这是无效的,因为PterodactylCage的实例(如错误消息所述)不能分配给ICage<IDinosaur>

ICage<IDinosaur> cage = new PterodactylCage(); // this won't compile


这与通用接口的协方差\协方差有关,您可以在Internet上的许多地方阅读它的内容(此处将描述广泛的主题)。

如果您具有以下接口定义:

public interface ICage<out T> // note "out" keyword


那将是合法的。但是,您不能在Trasport方法中使用out参数作为参数,因此不会解决您的问题。

进一步了解为什么这在直观上是非法的。假设这是合法的。然后,您将使用具有ICage<IDinosaur>方法的Tranport实例,该实例接受IDinosaur。但是基础类型是PterodactylCage,即ICage<Pterodactyl>。但是您可以将IDinosaur的任何实例传递给Transport方法,而不仅是Pterodactyl(记住-我们使用ICage<IDinosaur>),这样会使我们产生矛盾。这就是为什么从直觉上讲这是不合法的。

关于c# - 为什么以下带有接口(interface)的导入/导出模式不合法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37724942/

10-11 16:39