【问题标题】:Dynamic type casting to a generic list of an internal type动态类型转换为内部类型的通用列表
【发布时间】:2013-05-23 21:44:15
【问题描述】:

我正在使用第三方 API,我需要访问内部字段 ("_fieldOfA") 的私有字段 ("_fieldOfB")。下面的示例说明了该组合。我要查找的字段是内部类型列表(ClassCClassD 是内部的并且在同一个程序集中)。

 public abstract class ClassA
 {
    internal ClassB _fieldOfA;
 }

 public class ClassB
 {
    private readonly List<ClassC<ClassD, int>> _fieldOfB;
 }

我尝试过反射,但我似乎无法正确转换最终类型 - 动态类型保持 Object(请注意,我的类扩展了 ClassA

var assemblyHandle = typeof (ClassB).Assembly;
var genericTypeC = assemblyHandle.GetType("ApiNamespace.ClassC`2");
var typeD = assemblyHandle.GetType("ApiNamespace.ClassD");

var genericTypesForC = new Type[] { typeD, typeof(int) };
var typeC = genericTypeC.MakeGenericType(genericTypesForC);
var typeOfList = typeof(List<>).MakeGenericType(typeC);

var fieldOfAInfo= typeof(ClassA).GetField("_fieldOfA", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance);
var fieldOfAValue = fieldOfAInfo.GetValue(this);

var fieldOfBInfo= typeof(ClassB).GetField("_fieldOfB", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance);
var uncastedFieldOfBValue = fieldOfBInfo.GetValue(fieldOfAValue);

dynamic fieldOfBValue = Convert.ChangeType(uncastedFieldOfBValue, typeOfList);

有什么想法吗?

【问题讨论】:

  • 预警,如果你还没有弄清楚这一点......因为ClassC&lt;ClassD, int&gt;的项目是你看不到的内部类型,你将不得不使用反射使用列表它的对象(不仅仅是获取列表本身),因为你不能在编译时使用这些类型。
  • 话虽如此,您是否在调试器中检查了uncastedFieldOFBValue,以确定您实际上从反射调用中获得了某种形式的List&lt;&gt;
  • 是的,我已经使用调试器检查了uncastedFieldOFBValue,并且数据在那里,但我似乎无法以List&lt;&gt; 的身份访问它,它仍然是Object
  • 我创建了一个解决方法,方法是转换为IList,然后反射性地从列表中一一获取项目值。这并不漂亮,而且绝对是一个令人讨厌的 hack,但在 API 供应商可以发布他们的库的更新之前,它必须这样做。

标签: c# reflection casting


【解决方案1】:

您可以更轻松地访问 List&lt;ClassC&lt;ClassD, int&gt;&gt; 中的项目(根据 cmets 将对象转换为 IList 之后)是使用列表中的 Enumerable.Cast&lt;TResult&gt; 扩展方法为您提供枚举dynamic 对象;这样,您可以简单地让运行时为您绑定调用,而不是使用反射。

IList nonGenericList = uncastedFieldOfBValue as IList;
IEnumerable<dynamic> dynamicEnumerable = nonGenericList.Cast<dynamic>();

foreach (dynamic obj in dynamicEnumerable)
{
    // work with your objects here
}

当然,这只允许您访问位于第三方程序集中的实例上的public 方法和属性。如果您想使用内部结构,可以查看 one of these 博客文章,了解如何创建 DynamicObject 包装器,该包装器允许您使用反射将调用绑定到非公共成员。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-06
    • 2011-05-08
    • 1970-01-01
    相关资源
    最近更新 更多