【问题标题】:How to access generic property without knowing the closed generic type如何在不知道封闭泛型类型的情况下访问泛型属性
【发布时间】:2011-01-04 10:35:26
【问题描述】:

我有一个通用类型如下

public class TestGeneric<T>
{
    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;
}

为了确保我的对象是泛型类型。有问题的代码如下:

public static void Main()
{
    object myObject = new TestGeneric<string>("test"); // or from another source
    if (IsSubclassOfRawGeneric(typeof(TestGeneric<>), myObject.GetType()))
    {
        // the following gives an InvalidCastException
        // var data = ((TestGeneric<object>)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[] { });
    }
}

无论其类型如何,我都需要数据(好吧,如果我可以使用 GetType() 来询问其类型会很好,但不是必需的),因为我只想使用 ToString() 将其转储到 xml 中。

有什么建议吗?谢谢。

【问题讨论】:

标签: c# reflection casting generics


【解决方案1】:

哦,stackies...为什么没有人将我指向dynamic 类型?这是使代码更具可读性的完美用法示例:

dynamic dynObject = myObject;
object data = dynObject.Data;

【讨论】:

【解决方案2】:

在访问其泛型成员之前,您需要知道泛型类的封闭类型。使用TestGeneric&lt;&gt; 为您提供了开放类型定义,如果不指定泛型参数,就无法调用它。

你获取属性值最简单的方法是直接在使用的封闭类型上进行反射:

public static void Main()
{
    object myObject = new TestGeneric<string>("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[] { });
    }
}

【讨论】:

【解决方案3】:

啊,对不起。这是一个简单的错误,通用版本有效,当然必须阅读

var dataProperty = myObject.GetType().GetProperty("Data");
object data = dataProperty.GetValue(myObject, new object[] { });

【讨论】:

    【解决方案4】:

    对于 C# 6 及更高版本,我们可以使用 nameof 稍微改进 Paul 的回答:

    public static void Main()
    {
        object myObject = new TestGeneric<string>("test"); // or from another source
    
        var type = myObject.GetType();
    
        if (IsSubclassOfRawGeneric(typeof(TestGeneric<>), type))
        {
            var dataProperty = type.GetProperty(nameof(TestGeneric<object>.Data));
            object data = dataProperty.GetValue(myObject);
        }
    }
    

    请注意,将 type.GetProperty("Data") 替换为 type.GetProperty(nameof(TestGeneric&lt;object&gt;.Data)) 可为您提供编译时安全性(可以说也比使用 dynamic 方式更好)。

    同样使用object作为类型参数只是一种访问属性的方法,没有任何副作用或特殊含义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-19
      • 2017-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多