Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Using Reflection With Generic Property

I have a class which uses generic properties. For example:

class Person
{
    public MyGenericProperty<string> Field1
    {
        get { return field1; }
        set { field1 = value; }
    }

    private MyGenericProperty<string> field1= new MyInheritedGenericProperty<string>("Alan1");
}

I want to use this class with reflection at another class and i have a method like that

public void DoSomethingWithProperty(object sourceobject)
{
    foreach (var aProperty in sourceobject.GetType().GetProperties())
    {
        *if(aProperty.PropertyType == typeof(MyGenericProperty<>))*
        {
           *var obj = (MyGenericProperty<>)aProperty.GetValue(sourceobject, null);*
        }
    }
    return null;
}

I have two problem

1- How can do type check of generic property. In that example code of if(aProperty.PropertyType == typeof(MyGenericProperty<>)) does not work.

2- T of MyGenericProperty could be any class and how can cast MyGenericProperty class without knowing T by reflection as

var obj = (MyGenericProperty<>)aProperty.GetValue(sourceobject, null);

Thank for helps.

like image 596
user1252105 Avatar asked Jan 13 '23 13:01

user1252105


1 Answers

Firstly, it's important to understand that you don't have a "generic property" - there's no such thing. You have a property whose type is a generic type... and that's not the same thing. (Compare that with a generic type or a generic method, each of which is genuinely generic in terms of introducing new type parameters.)

You can test it using this code:

if (aProperty.PropertyType.IsGenericType &&
    aProperty.GetGenericTypeDefinition() == typeof(MyGenericProperty<>))

But as for the casting - it depends on what you want to do with the value afterwards. You may want to declare a non-generic base type of MyGenericProperty<> containing all the members which don't depend on the type parameter. I'd typically give that the same name as the generic type (e.g. MyGenericProperty) just without giving it type parameters. Then if you only need one of those members, you can use:

if (aProperty.PropertyType.IsGenericType &&
    aProperty.GetGenericTypeDefinition() == typeof(MyGenericProperty<>))
{
    var value = (MyGenericProperty) aProperty.GetValue(sourceObject, null);
    // Use value
}

But then in that case you could use Type.IsAssignableFrom anyway:

if (typeof(MyGenericProperty).IsAssignableFrom(aProperty.PropertyType))
{
    var value = (MyGenericProperty) aProperty.GetValue(sourceObject, null);
    // Use value
}

If these hints don't help you, please give more details of what you're trying to do.

like image 117
Jon Skeet Avatar answered Jan 19 '23 07:01

Jon Skeet