【问题标题】:Reflection - casting object to interface<interface>反射 - 将对象转换为 interface<interface>
【发布时间】:2018-11-10 23:39:57
【问题描述】:

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 实现接口并设置 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);
}

【问题讨论】:

标签: c# generics reflection interface


【解决方案1】:

每天都会有人问这个问题。再来一次!

当您需要一篮水果时,是否可以使用一篮苹果?没有。

为什么不呢?因为你可以把一根香蕉放进一篮水果里,但你不能把一根香蕉放进一篮苹果里。

因此,你不能在需要一篮水果的地方使用一篮苹果。

同样,一篮水果也不能用作一篮苹果,因为它可能已经包含了一根香蕉。

关系“a C&lt;X&gt; can be used as a C&lt;Y&gt; if an X can be used as a Y”称为协方差,C#只支持协方差非常有限的情况:

  • C&lt;T&gt; 必须是接口或委托
  • 必须将接口或委托声明标记为对变化安全。
  • 编译器必须成功验证方差声明是安全的。
  • XY 都必须是引用类型。

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

像这样标记IDataPointProcessor&lt;T&gt;

interface IDataPointProcessor<out T>

大致意思是“T 仅用于输出位置,从不用于输入位置”。如果篮子不能添加水果,那么反对意见——你不能把香蕉放在一篮苹果里——就消失了,它就变得合法了。

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

这就是为什么您可以将IEnumerable&lt;Giraffe&gt; 用作IEnumerable&lt;Animal&gt; 的原因——满足所有四个条件。

【讨论】:

    【解决方案2】:

    我已经解决了这个问题,How to reflect an interfaced type<t> at runtime 通过不使用反射完全避免了这个问题。如果有人感兴趣,请在该页面上给出完整答案

    感谢大家的宝贵时间

    @Eric我确实事先找到了你的文章,但当时我头疼!

    【讨论】:

      【解决方案3】:

      据我了解,泛型类型在 C# 编译器中的工作方式是在编译时在这些泛型参数中使用的强类型(意味着它们在您的代码中使用)是作为强类型类动态生成的(可能在 MSIL 层上)。

      因此,在运行时,您的对象没有继承具有泛型类型的 Type,而是继承了强类型的类型。

      您可以为每种可能的强类型类型构建一个 switch case 并尝试对其进行强制转换。

      【讨论】:

        猜你喜欢
        • 2015-01-17
        • 2015-01-14
        • 1970-01-01
        • 1970-01-01
        • 2021-08-06
        • 1970-01-01
        • 2016-09-18
        • 1970-01-01
        • 2012-02-14
        相关资源
        最近更新 更多