Get property of generic class

C#

C# Problem Overview


I have a generic class, and an object value where obj.GetType().GetGenericTypeDefinition() == typeof(Foo<>).

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

How do I get the value of Items from obj? Remember, obj is an Object, I can't cast obj as Foo because I don't know what T is.

I was hoping to use reflection for this, but each time I do GetProperty("Items") it returns null. However, if someone knows a good way to do this without reflection, by all means.

Let's say my code looks like this:

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

C# Solutions


Solution 1 - C#

You should be able to use:

Type t = obj.GetType();

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

object list = prop.GetValue(obj);

You will not be able to cast as a List<T> directly, of course, as you don't know the type T, but you should still be able to get the value of Items.


Edit:

The following is a complete example, to demonstrate this working:

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

Solution 2 - C#

@ReedCopsey is absolutely correct, but in case you're really asking the question "How do I fish out the generic details of a type?", here's some "Fun with 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);
	}
}

Solution 3 - C#

Something like this should do the trick:

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

Solution 4 - C#

You have to use System.Reflection namespace to execute the program successfully.

This program gives you Property Name and Value of any Generic Class

You can check this code fiddle on C# Online Rexter Tool Compiler at

using System;
using System.Reflection;

namespace GenericPropertyExample
{
    //Declaring a Sample Class 
    public class class1
    {
        public string prop1 { get; set; }
        public string prop2 { get; set; }

    }
    public class Program
    {
        public static void Main(string[] args)
        {
            //Creating Class Object
            class1 objClass1 = new class1 { prop1 = "value1", prop2 = "value2" };

            //Passing Class Object to GenericPropertyFinder Class
            GenericPropertyFinder<class1> objGenericPropertyFinder = new GenericPropertyFinder<class1>();
            objGenericPropertyFinder.PrintTModelPropertyAndValue(objClass1);
            Console.ReadLine();
        }

        //Declaring a Generic Handler Class which will actually give Property Name,Value for any given class.
        public class GenericPropertyFinder<TModel> where TModel : class
        {
            public void PrintTModelPropertyAndValue(TModel tmodelObj)
            {
                //Getting Type of Generic Class Model
                Type tModelType = tmodelObj.GetType();

                //We will be defining a PropertyInfo Object which contains details about the class property 
                PropertyInfo[] arrayPropertyInfos = tModelType.GetProperties();

                //Now we will loop in all properties one by one to get value
                foreach (PropertyInfo property in arrayPropertyInfos)
                {
                    Console.WriteLine("Name of Property is\t:\t" + property.Name);
                    Console.WriteLine("Value of Property is\t:\t" + property.GetValue(tmodelObj).ToString());
                    Console.WriteLine(Environment.NewLine);
                }
            }
        }
    }
}

Solution 5 - C#

Hey guys ive been struggeling with the same issue with generic typs and finally found the solution that gets the value --------Small code snippet of the method that does the trick ------------------

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiongunr2171View Question on Stackoverflow
Solution 1 - C#Reed CopseyView Answer on Stackoverflow
Solution 2 - C#JerKimballView Answer on Stackoverflow
Solution 3 - C#sa_ddam213View Answer on Stackoverflow
Solution 4 - C#vibs2006View Answer on Stackoverflow
Solution 5 - C#René MouritsenView Answer on Stackoverflow