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)
每天都会问这个问题.再一次!
当你需要一篮子水果时,是否可以使用一篮子苹果?没有.
为什么不?因为你可以把香蕉放入一篮子水果中,但你不能把香蕉放入一篮子苹果中.
因此,你不能使用一篮子苹果,需要一篮子水果.
同样,一篮子水果不能作为一篮子苹果使用,因为它可能已含有香蕉.
关系"a C<X>可以用作C<Y>if如果X可以用作a Y"被称为协方差,而C#仅在非常有限的情况下支持协方差:
C<T> 必须是接口或委托X并Y必须是引用类型.在你的情况下,你有第一和第四个属性,但你没有第二个和第三个属性.
这样标记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>- 满足所有四个条件.