我正在使用第三方API,我需要访问内部字段("_fieldOfA")的私有字段("_fieldOfB")。下面的例子说明了这个组合。我正在寻找的字段是内部类型的列表(ClassC
和ClassD
是内部的,在同一个程序集中)。
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);
任何想法?
您可以更轻松地访问List<ClassC<ClassD, int>>
中的项目(在您将对象转换为IList
之后,根据注释)是在列表中使用Enumerable.Cast<TResult>
扩展方法来为您提供dynamic
对象的枚举;这样,您就可以让运行时为您绑定调用,而不是使用反射。
IList nonGenericList = uncastedFieldOfBValue as IList;
IEnumerable<dynamic> dynamicEnumerable = nonGenericList.Cast<dynamic>();
foreach (dynamic obj in dynamicEnumerable)
{
// work with your objects here
}
当然,这只允许您访问位于第三方程序集中的实例上的public
方法和属性。如果您想尝试内部操作,可以查看其中一篇博客文章,了解如何创建一个DynamicObject
包装器,该包装器允许您使用反射绑定对非公共成员的调用。