51

ジェネリック クラスとオブジェクト値 where obj.GetType().GetGenericTypeDefinition() == typeof(Foo<>).

class Foo<T>
{
    public List<T> Items { get; set; }
}

Itemsfromの値を取得するにはどうすればよいobjですか? objが であることを忘れないでください。が何であるかがわからないため、 as としてObjectキャストすることはできません。objFooT

これにリフレクションを使用したいと思っていましたが、毎回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
4

5 に答える 5

88

以下を使用できるはずです。

Type t = obj.GetType();

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

object list = prop.GetValue(obj);

List<T>もちろん、 type がわからないため、 を直接キャストすることはできませんが、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
    }
}
于 2013-01-02T21:28:15.977 に答える
13

@ReedCopseyは絶対に正しいですが、「タイプの一般的な詳細をどのように取得するのですか?」という質問を本当にしている場合は、「Reflectionを使って楽しむ」をいくつか紹介します。

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);
    }
}
于 2013-01-02T21:37:19.073 に答える
4

このような何かがトリックを行う必要があります:

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);
}
于 2013-01-02T21:35:53.903 に答える
0

こんにちはみんな、一般的なタイプで同じ問題に苦しんでいて、最終的に値を取得する解決策を見つけました--------トリックを行うメソッドの小さなコードスニペット---------- -------

    public void printFields()
    {
        // Is the list empty
        if (this.list_.Count == 0)
        {
            //Y => Forced exit no object info
            return;
        }

        try
        {
            // Get first item from list
            T item = this.list_[0];

            // Get the type of object
            //**Type thisType = item.GetType();

            // Get array of all fields
            FieldInfo[] thisFieldInfo = item.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            // Loop through all fields and show its info
            for (int ix = 0; ix < thisFieldInfo.Length; ix++)
            {
                // Get Field value
                String strVal = thisFieldInfo[ix].GetValue(item).ToString();

                // Display item
                Console.WriteLine("'{0}' is a {1} and has value {2}", thisFieldInfo[ix].Name, thisFieldInfo[ix].FieldType, strVal);
            }


        }
        catch (SecurityException e)
        {
            Console.WriteLine("Exception: " + e.Message);
        }
    }
于 2020-05-20T13:56:24.370 に答える