反射 - 将对象转换为接口<interface>

Jon*_*mee 2 c# generics reflection interface

以下是如何在运行时反映接口类型<t>我有一个类型的实例我知道从基类型继承DataPointProcessorBase这个基类相对简单

public abstract class DataPointProcessorBase<T> : IDataPointProcessor<T> where T : class, IDataPointInput, new()
{            
    public abstract DataPointOutputBase GetOutput(T input);
}
Run Code Online (Sandbox Code Playgroud)

Age_Input实现接口,Age_Processor设置为接收它

public class Age_Input : DataPointInputBase, IDataPointInput
{
    public int AgeExact { get; set; }    
}
public class Age_Processor : DataPointProcessorBase<Age_Input> 
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

使用反射,我是正确的一半,所以我可以调用GetOutput()

任何想法为什么我不能进入下面的声明?

var instance = Activator.CreateInstance(type);

if (instance is IDataPointProcessor<IDataPointInput>)//why can I not cast interface here?
{
    //false        
}

if (instance is IDataPointProcessor<Age_Input>)//hard-coded - works fine
{
    var processor = instance as IDataPointProcessor<Age_Input>;
    Age_Input temp = item as Age_Input;
    if (temp is IDataPointInput)
    {
        //also true
    }
    var result = processor.GetOutput(temp);
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 9

每天都会问这个问题.再一次!

当你需要一篮子水果时,是否可以使用一篮子苹果?没有.

为什么不?因为你可以把香蕉放入一篮子水果中,但你不能把香蕉放入一篮子苹果中.

因此,你不能使用一篮子苹果,需要一篮子水果.

同样,一篮子水果不能作为一篮子苹果使用,因为它可能已含有香蕉.

关系"a C<X>可以用作C<Y>if如果X可以用作a Y"被称为协方差,而C#仅在非常有限的情况下支持协方差:

  • C<T> 必须是接口或委托
  • 必须将接口或委托声明标记为方差安全.
  • 编译器必须成功验证方差声明是否安全.
  • 双方XY必须是引用类型.

在你的情况下,你有第一和第四个属性,但你没有第二个和第三个属性.

这样标记IDataPointProcessor<T>:

interface IDataPointProcessor<out T>
Run Code Online (Sandbox Code Playgroud)

这意味着大致"T仅用于输出位置,从不输入位置".如果篮子没有能力添加水果那么反对 - 你不能把香蕉放入一篮子苹果 - 消失,它变得合法.

如果编译成功,那么协方差将开始工作IDataPointProcessor.如果没有,你可能使用T在一个位置T可以流动.规则比我在这里总结的要简单一些; 如果你需要详细的描述,我在这里写了一篇:https://blogs.msdn.microsoft.com/ericlippert/2009/12/03/exact-rules-for-variance-validity/

这就是为什么你可以使用IEnumerable<Giraffe>一个IEnumerable<Animal>- 满足所有四个条件.