c# - 反射 - 将对象转换到接口(interface)<interface>

标签 c# generics reflection interface

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)声明必须标记为安全的变化。
  • 编译器必须成功验证方差声明是安全的。
  • 两者都是 XY必须是引用类型。

在您的例子中,您获得了第一个和第四个属性,但没有获得第二个和第三个属性。

标记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/

相关文章:

c# - 你如何读取正在使用的文件?

c# - 在 JQGrid ReloadGrid 上显示时间戳

c# - ASP.NET Core Controller 中奇怪的死锁情况

c# - 如何传递要使用 LINQ 调用的函数委托(delegate)?

java - Java Method 对象是否可以通过标识(即 ==)进行比较,还是必须使用 equals()?

scala - Scala 中使用 TypeTag 和 ClassTag 的多态实例化

c# - 根事务回滚时嵌套事务会回滚吗?

java - Java 中的 T 和继承

java - 通配符捕获错误: why?

java - Java EE/Jakarta EE 是否支持 Java 模块系统?是否可以使用 Java 模块系统制作 Web 应用程序?