Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access generic property without knowing the closed generic type

I have a generic Type as follows

public class TestGeneric<T>
{
    public T Data { get; set; }
    public TestGeneric(T data)
    {
        this.Data = data;
    }
}

If i have now an object (which is coming from some external source) from which i know that it's type is of some closed TestGeneric<>, but i don't know the TypeParameter T. Now I need to access the Data of my object. Problem is that i can't cast the object, since i don't know exactly to which closed TestGeneric.

I use

// 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;
}

to make sure, my object is of the generic type. The code in question is as follows:

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[] { });
    }
}

I need the Data regardless of its type (well, if i could ask for its type using GetType() would be fine, but not necessary) since i just want to dump it in xml using ToString().

Any suggestions? Thanx.

like image 855
Martin Booka Weser Avatar asked Jan 04 '11 10:01

Martin Booka Weser


2 Answers

Ahh, sorry for that. It was a simple mistake, the generic version works, of course it must read

var dataProperty = myObject.GetType().GetProperty("Data");
object data = dataProperty.GetValue(myObject, new object[] { });
like image 83
Martin Booka Weser Avatar answered Oct 31 '22 19:10

Martin Booka Weser


You need to know the closed type of a generic class before you can access its generic members. The use of TestGeneric<> gives you the open type definition, which cannot be invoked without specifying the generic arguments.

The simplest way for you to get the value of the property is to reflect on the closed type in use directly:

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[] { });
    }
}
like image 39
Paul Turner Avatar answered Oct 31 '22 17:10

Paul Turner