从 How to reflect an interfaced type<t> at runtime 开始我有一个类型的实例,我知道它是从基本类型 DataPointProcessorBase 继承而来的 这个基类比较简单
public abstract class DataPointProcessorBase<T> : IDataPointProcessor<T> where T : class, IDataPointInput, new()
{
public abstract DataPointOutputBase GetOutput(T input);
}
Age_Input 实现接口(interface),Age_Processor 设置接收它
public class Age_Input : DataPointInputBase, IDataPointInput
{
public int AgeExact { get; set; }
}
public class Age_Processor : DataPointProcessorBase<Age_Input>
{
...
}
使用反射,我已经完成了正确转换的一半,所以我可以调用 GetOutput()
为什么我不能进入下面的第一个 if 语句?
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);
}
最佳答案
这个问题每天都会被问到。再来一次!
当你需要一篮子水果时,是否可以使用一篮子苹果?没有。
为什么不呢?因为你可以将一根香蕉放入一篮子水果中,但你不能将一根香蕉放入一篮子苹果中。
因此,您不能在需要一篮子水果的地方使用一篮子苹果。
同样,一篮子水果不能用作一篮子苹果,因为它可能已经包含香蕉。
关系“a C<X>
can be used as a C<Y>
if an X
can be used as a Y
”称为协方差,C# 仅支持协方差非常有限的情况:
-
C<T>
必须是接口(interface)或委托(delegate) - 接口(interface)或委托(delegate)声明必须标记为安全的变化。
- 编译器必须成功验证方差声明是安全的。
- 两者都是
X
和Y
必须是引用类型。
在您的例子中,您获得了第一个和第四个属性,但没有获得第二个和第三个属性。
标记IDataPointProcessor<T>
像这样:
interface IDataPointProcessor<out T>
大致意思是“T 仅用于输出位置,从不用于输入位置”。如果篮子不能添加水果,那么反对意见(您不能将香蕉放入一篮子苹果中)就消失了,它就变得合法了。
如果编译成功,那么协方差将开始在 IDataPointProcessor
上工作.如果不是,您可能正在使用 T
在一个T
的位置可以流入。这些规则比我在这里总结的要微妙一些;如果您需要详细说明,我在这里写了一个:https://blogs.msdn.microsoft.com/ericlippert/2009/12/03/exact-rules-for-variance-validity/
这就是您可以使用 IEnumerable<Giraffe>
的原因作为IEnumerable<Animal>
-- 满足所有四个条件。
关于c# - 反射 - 将对象转换到接口(interface)<interface>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50633096/