C# 获取泛型类的属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14129421/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get property of generic class
提问by gunr2171
I have a generic class, and an object value where obj.GetType().GetGenericTypeDefinition() == typeof(Foo<>)
.
我有一个通用类和一个对象值,其中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.
我如何获得Items
from的值obj
?请记住,obj
是Object
,我不能转换obj
为 asFoo
因为我不知道是什么T
。
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.
我希望为此使用反射,但每次我这样做GetProperty("Items")
都会返回 null。但是,如果有人知道一种无需反思就可以做到这一点的好方法,那么无论如何。
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
采纳答案by Reed Copsey
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
.
List<T>
当然,您将无法直接转换为 a ,因为您不知道 type T
,但您仍然应该能够获得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
}
}
回答by sa_ddam213
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);
}
回答by JerKimball
@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":
@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);
}
}
回答by vibs2006
You have to use System.Reflectionnamespace to execute the program successfully.
您必须使用System.Reflection命名空间才能成功执行程序。
This program gives you Property Name and Value of any Generic Class
该程序为您提供任何通用类的属性名称和值
You can check this code fiddle on C# Online Rexter Tool Compilerat
您可以检查这些代码的小提琴C#在线Rexter工具编译器在
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);
}
}
}
}
}
回答by René Mouritsen
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);
}
}