获取泛型类的属性

gun*_*171 34 c#

我有一个泛型类,一个对象值在哪里obj.GetType().GetGenericTypeDefinition() == typeof(Foo<>).

class Foo<T>
{
    public List<T> Items { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我如何获得的值Itemsobj?记住,obj是一个Object,我不能演员obj,Foo因为我不知道是什么T.

我希望为此使用反射,但每次我这样做GetProperty("Items")都会返回null.但是,如果有人知道一个好的方法,无需反思就可以做到这一点.

假设我的代码如下所示:

//just to demonstrate where this comes from
Foo<int> fooObject = new Foo<int>();
fooObject.Items = someList;
object obj = (object)fooObject;

//now trying to get the Item value back from obj
//assume I have no idea what <T> is
PropertyInfo propInfo = obj.GetType().GetProperty("Items"); //this returns null
object itemValue = propInfo.GetValue(obj, null); //and this breaks because it's null
Run Code Online (Sandbox Code Playgroud)

Ree*_*sey 60

你应该可以使用:

Type t = obj.GetType();

PropertyInfo prop = t.GetProperty("Items");

object list = prop.GetValue(obj);
Run Code Online (Sandbox Code Playgroud)

List<T>当然,你不能直接演员,因为你不知道类型T,但是你仍然可以获得它的价值Items.


编辑:

以下是一个完整的示例,以演示此工作:

// Define other methods and classes here
class Foo<T>
{
    public List<T> Items { get; set; }
}

class Program
{
    void Main()
    {   
        //just to demonstrate where this comes from
        Foo<int> fooObject = new Foo<int>();
        fooObject.Items = new List<int> { 1, 2, 3};
        object obj = (object)fooObject;

        //now trying to get the Item value back from obj
        //assume I have no idea what <T> is
        PropertyInfo propInfo = obj.GetType().GetProperty("Items"); //this returns null
        object itemValue = propInfo.GetValue(obj, null);

        Console.WriteLine(itemValue);
                    // Does not print out NULL - prints out System.Collections.Generic.List`1[System.Int32]


        IList values = (IList)itemValue;
        foreach(var val in values)
            Console.WriteLine(val); // Writes out values appropriately
    }
}
Run Code Online (Sandbox Code Playgroud)


Jer*_*all 10

@ReedCopsey是完全正确的,但如果您真的问"我如何剔除某种类型的通用细节?",这里有一些"反思的乐趣":

public void WhatsaFoo(object obj)
{
    var genericType = obj.GetType().GetGenericTypeDefinition();
    if(genericType == typeof(Foo<>))
    {
        // Figure out what generic args were used to make this thing
        var genArgs = obj.GetType().GetGenericArguments();

        // fetch the actual typed variant of Foo
        var typedVariant = genericType.MakeGenericType(genArgs);

        // alternatively, we can say what the type of T is...
        var typeofT = obj.GetType().GetGenericArguments().First();

        // or fetch the list...
        var itemsOf = typedVariant.GetProperty("Items").GetValue(obj, null);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @gunr2171 嗯,可能是因为我并没有试图真正回答上述问题......*耸耸肩*我不在乎否决票,但是我确实喜欢谈论简洁的代码。:) (2认同)

sa_*_*213 5

像这样的事情应该可以解决问题:

var foo = new Foo<int>();
foo.Items = new List<int>(new int[]{1,2,3});

// this check is probably not needed, but safety first :)
if (foo.GetType().GetProperties().Any(p => p.Name == "Items"))
{
    var items = foo.GetType().GetProperty("Items").GetValue(foo, null);
}
Run Code Online (Sandbox Code Playgroud)