从未知对象获取属性和值

时间:2010-11-10 13:11:03

标签: c# reflection

从PHP的世界来看,我决定给C#一个机会。我有一个搜索,但似乎无法找到如何做到与此相当的答案。

$object = new Object();

$vars = get_class_vars(get_class($object));

foreach($vars as $var)
{
    doSomething($object->$var);
}

我基本上有一个对象列表。该对象可以是三种不同类型之一,并且具有一组公共属性。我希望能够获得对象的属性列表,循环它们然后将它们写入文件。 我认为这与c#反射有关,但这对我来说都是新的。

非常感谢任何帮助。

14 个答案:

答案 0 :(得分:247)

这应该这样做:

Type myType = myObject.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());

foreach (PropertyInfo prop in props)
{
    object propValue = prop.GetValue(myObject, null);

    // Do something with propValue
}

答案 1 :(得分:17)

是的,反思将是要走的路。首先,您将获得表示列表中实例的类型(在运行时)的Type。您可以致电GetType method on Object来完成此操作。因为它位于Object类上,所以它可以通过 .NET中的每个对象调用,因为所有类型都来自Objectwell, technically, not everything,但这在此不重要)。

获得Type实例后,您可以调用GetProperties method获取PropertyInfo个实例,这些实例代表Type上有关属性的运行时信息。

注意,您可以使用GetProperties的重载来帮助对您检索的属性进行分类。

从那里,您只需将信息写入文件。

上面的代码翻译成:

// The instance, it can be of any type.
object o = <some object>;

// Get the type.
Type type = o.GetType();

// Get all public instance properties.
// Use the override if you want to classify
// which properties to return.
foreach (PropertyInfo info in type.GetProperties())
{
    // Do something with the property info.
    DoSomething(info);
}

请注意,如果您需要方法信息或字段信息,则必须分别调用GetMethodsGetFields方法的重载之一。

另请注意,将成员列出到文件是一回事,但不应使用此信息来基于属性集来驱动逻辑。

假设您可以控制类型的实现,您应该从公共基类派生或实现公共接口并对其进行调用(您可以使用asis运算符帮助确定您在运行时使用的基类/接口。)

但是,如果你不控制这些类型定义并且必须根据模式匹配来驱动逻辑,那就没关系。

答案 2 :(得分:15)

void Test(){
    var obj = new{a="aaa", b="bbb"};

    var val_a = obj.GetValObjDy("a"); //="aaa"
    var val_b = obj.GetValObjDy("b"); //="bbb"
}
//create in a static class
static public object GetValObjDy(this object obj, string propertyName)
{            
     return obj.GetType().GetProperty(propertyName).GetValue(obj, null);
}

答案 3 :(得分:10)

好吧,在C#中它是相似的。 这是最简单的例子之一(仅适用于公共属性):

var someObject = new { .../*properties*/... };
var propertyInfos = someObject.GetType().GetProperties();
foreach (PropertyInfo pInfo in PropertyInfos)
{
    string propertyName = pInfo.Name; //gets the name of the property
    doSomething(pInfo.GetValue(someObject,null));
}

答案 4 :(得分:8)

从属性名称

获取特定属性值
public class Bike{
public string Name {get;set;}
}

Bike b = new Bike {Name = "MyBike"};

从属性的字符串名称

访问Name的属性值
public object GetPropertyValue(string propertyName)
{
//returns value of property Name
return this.GetType().GetProperty(propertyName).GetValue(this, null);
} 

答案 5 :(得分:3)

您可以使用 GetType - GetProperties - Linq Foreach

obj.GetType().GetProperties().ToList().ForEach(p =>{
                                                        //p is each PropertyInfo
                                                        DoSomething(p);
                                                    });

答案 6 :(得分:2)

我使用以下内容将IEnumerable<T>转换为DataTable,其中包含代表T属性的列,IEnumerable中的每个项都有一行:< / p>

public static DataTable ToDataTable<T>(IEnumerable<T> items)
{
    var table = CreateDataTableForPropertiesOfType<T>();
    PropertyInfo[] piT = typeof(T).GetProperties();
    foreach (var item in items)
    {
        var dr = table.NewRow();
        for (int property = 0; property < table.Columns.Count; property++)
        {
            if (piT[property].CanRead)
            {
                var value = piT[property].GetValue(item, null);
                if (piT[property].PropertyType.IsGenericType)
                {
                    if (value == null)
                    {
                        dr[property] = DBNull.Value;
                    }
                    else
                    {
                        dr[property] = piT[property].GetValue(item, null);
                    }
                }
                else
                {
                    dr[property] = piT[property].GetValue(item, null);
                }
            }
        }
        table.Rows.Add(dr);
    }
    return table;
}

public static DataTable CreateDataTableForPropertiesOfType<T>()
{
    DataTable dt = new DataTable();
    PropertyInfo[] piT = typeof(T).GetProperties();
    foreach (PropertyInfo pi in piT)
    {
        Type propertyType = null;
        if (pi.PropertyType.IsGenericType)
        {
            propertyType = pi.PropertyType.GetGenericArguments()[0];
        }
        else
        {
            propertyType = pi.PropertyType;
        }
        DataColumn dc = new DataColumn(pi.Name, propertyType);

        if (pi.CanRead)
        {
            dt.Columns.Add(dc);
        }
    }
    return dt;
}

这有点“过分复杂”,但实际上看到结果是非常好的,因为你可以给它一个List<T>,例如:

public class Car
{
    string Make { get; set; }
    int YearOfManufacture {get; set; }
}

您将返回一个具有以下结构的DataTable:

  

Make(string)
  YearOfManufacture(int)

List<Car>

中每个项目占一行

答案 7 :(得分:1)

此示例修剪对象的所有字符串属性。

public static void TrimModelProperties(Type type, object obj)
{
    var propertyInfoArray = type.GetProperties(
                                    BindingFlags.Public | 
                                    BindingFlags.Instance);
    foreach (var propertyInfo in propertyInfoArray)
    {
        var propValue = propertyInfo.GetValue(obj, null);
        if (propValue == null) 
            continue;
        if (propValue.GetType().Name == "String")
            propertyInfo.SetValue(
                             obj, 
                             ((string)propValue).Trim(), 
                             null);
    }
}

答案 8 :(得分:0)

我还没有找到这个,比如Application对象。然而,我已经取得了成功

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();

string rval = serializer.Serialize(myAppObj);

答案 9 :(得分:0)

使用Linq的一线解决方案...

var obj = new {Property1: 1, Property2: 2};
var property1 = obj.GetType().GetProperties().First(o => o.Name == "Property1").GetValue(obj , null);

答案 10 :(得分:0)

public Dictionary<string, string> ToDictionary(object obj)
{
    Dictionary<string, string> dictionary = new Dictionary<string, string>();

    Type objectType = obj.GetType();
    IList<PropertyInfo> props = new List<PropertyInfo>(objectType.GetProperties());

    foreach (PropertyInfo prop in props)
    {
        object propValue = prop.GetValue(obj, null);
        dictionary.Add(prop.Name, propValue.ToString());
    }

    return dictionary;
}

答案 11 :(得分:0)

from django.db.models import Max

Users.objects.all().aggregate(Max('Events.timestamp'))

答案 12 :(得分:-1)

你可以试试这个:

string[] arr = ((IEnumerable)obj).Cast<object>()
                                 .Select(x => x.ToString())
                                 .ToArray();

每个数组实现IEnumerable接口

答案 13 :(得分:-1)

    public Dictionary<string, string> ToDictionary(object obj)
    {
        Dictionary<string, string> dictionary = new Dictionary<string, string>();

        Type objectType = obj.GetType();
        IList<PropertyInfo> props = new List<PropertyInfo>(objectType.GetProperties());

        foreach (PropertyInfo prop in props)
        {
            object propValue = prop.GetValue(obj, null);
            dictionary.Add(prop.Name, propValue.ToString());
        }

        return dictionary;