如何在不知道封闭generics类型的情况下访问通用属性
我有一个通用类型如下
public class TestGeneric { public T Data { get; set; } public TestGeneric(T data) { this.Data = data; } }
如果我现在有一个对象(来自某个外部源),我知道它的类型是一些封闭的TestGeneric ,但我不知道TypeParameter T.现在我需要访问我的对象的数据。 问题是我无法转换对象,因为我不确切知道哪个封闭的TestGeneric。
我用
// thx to http://stackoverflow.com/questions/457676/c-reflection-check-if-a-class-is-derived-from-a-generic-class private static bool IsSubclassOfRawGeneric(Type rawGeneric, Type subclass) { while (subclass != typeof(object)) { var cur = subclass.IsGenericType ? subclass.GetGenericTypeDefinition() : subclass; if (rawGeneric == cur) { return true; } subclass = subclass.BaseType; } return false; }
为了确保,我的对象是generics类型。 有问题的代码如下:
public static void Main() { object myObject = new TestGeneric("test"); // or from another source if (IsSubclassOfRawGeneric(typeof(TestGeneric), myObject.GetType())) { // the following gives an InvalidCastException // var data = ((TestGeneric)myObject).Data; // if i try to access the property with reflection // i get an InvalidOperationException var dataProperty = typeof(TestGeneric).GetProperty("Data"); object data = dataProperty.GetValue(myObject, new object[] { }); } }
我需要Data而不管它的类型(好吧,如果我可以使用GetType()来询问它的类型会很好,但不是必需的)因为我只想使用ToString()将它转储到xml中。
有什么建议? 感谢名单。
在访问其generics成员之前,您需要知道generics类的封闭类型。 TestGeneric<>
的使用为您提供了开放类型定义,如果不指定generics参数,则无法调用该定义。
获取属性值的最简单方法是直接反映使用中的封闭类型:
public static void Main() { object myObject = new TestGeneric("test"); // or from another source var type = myObject.GetType(); if (IsSubclassOfRawGeneric(typeof(TestGeneric<>), type)) { var dataProperty = type.GetProperty("Data"); object data = dataProperty.GetValue(myObject, new object[] { }); } }
哦,堆叠……为什么没有人指我dynamic
类型? 这是一个完美的用法示例,它使代码更具可读性:
dynamic dynObject = myObject; object data = dynObject.Data;
啊,对不起。 这是一个简单的错误,generics版本有效,当然它必须阅读
var dataProperty = myObject.GetType().GetProperty("Data"); object data = dataProperty.GetValue(myObject, new object[] { });
使用C#6及以上,我们可以使用nameof
来略微改进Paul的答案:
public static void Main() { object myObject = new TestGeneric("test"); // or from another source var type = myObject.GetType(); if (IsSubclassOfRawGeneric(typeof(TestGeneric<>), type)) { var dataProperty = type.GetProperty(nameof(TestGeneric
请注意,将type.GetProperty("Data")
替换为type.GetProperty(nameof(TestGeneric
会为您提供编译时安全性(因此可以说比使用dynamic
方式更好)。
使用object
作为类型参数只是一种访问属性的方法,并且没有任何副作用或特定含义。
- 我是否可以创建一个Azure Webjob,它将function公开给仪表板但不使用Azure存储?
- 如何在OrmLite ServiceStack中增加命令超时?
- 如何在C#Asp.net中将SELECT sql查询结果保存在一个数组中
- 无法加载{myassembly}导入的过程
- 什么是运算符`| =`? 我怎样才能在C#中实现它?
- AutoMapper AssertConfigurationIsValid是否足以确保良好的映射?
- 使用iTextSharp将pdf显示到网页?
- 将CIM_DateTime解析为.Net DateTime
- 在IIS 7.5中部署的MVC3 – 继续获取CS1009:无法识别的转义序列错误消息