从未知对象获取属性和值


150

从PHP的世界出发,我决定尝试一下C#。我进行了搜索,但似乎找不到与之等效的答案。

$object = new Object();

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

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

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

任何帮助将不胜感激。


9
附带说明:在列表中具有不同类型的对象(没有通用的基类或接口)不是一种好的编程风格,至少在c#中不是。
Albin Sunnanbo 2010年

Answers:


284

应该这样做:

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
}

PropertyInfo来自哪里?
乔纳森·多斯·桑托斯

8
@jonathan System.Reflection命名空间
Cocowalla 2013年

21
根本没有必要从数组创建列表,只需PropertyInfo[] props = input.GetType().GetProperties();
VladL 2014年

2
您要使用来更新2017年答案Newtonsoft.Json.JsonConvert吗?
Vayne

1
@clone是完全不同的方式。如果您认为这是一种有效的方法,则应该发布答案
Cocowalla

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

17

是的,反思将是必经之路。首先,您将获得,Type它代表列表中实例的类型(在运行时)。您可以通过在GetTypeObject调用方法来实现。因为它在Object类上,所以.NET中的每个对象可以调用它,因为所有类型都是从它派生的Object(从技术上讲,不是所有的东西,但这在这里并不重要)。

拥有Type实例后,您可以调用GetProperties方法以获取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);
}

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

还要注意,列出文件的成员是一回事,但是您不应该使用此信息来驱动基于属性集的逻辑。

假设您可以控制这些类型的实现,则应从一个公共基类派生或实现一个公共接口并对其进行调用(可以使用asor is运算符来帮助确定您正在使用的基类/接口。运行)。

但是,如果您不控制这些类型定义,而必须基于模式匹配来驱动逻辑,那很好。


11

好吧,在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));
}

9

从属性名称获取特定的属性值

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

3

您可以使用GetType-GetProperties-Linq Foreach

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

3

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

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

2

这是我用来将转换IEnumerable<T>为的方式DataTable,其中包含代表T的属性的列,并且IEnumerable

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:

制作(字符串)
YearOfManufacture(整数)

每项中有一行 List<Car>


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

0

应用程序对象说,我还没有发现这一点。但是我已经成功

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

string rval = serializer.Serialize(myAppObj);

2
如果可以避免,请不要使用JavaScriptSerializer。有很多原因
NunoAndré18年

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

0
    /// get set value field in object to object new (two object  field like ) 

    public static void SetValueObjectToObject (object sourceObj , object resultObj)
    {
        IList<PropertyInfo> props = new List<PropertyInfo>(sourceObj.GetType().GetProperties());
        foreach (PropertyInfo prop in props)
        {
            try
            {
                //get value in sourceObj
                object propValue = prop.GetValue(sourceObj, null);
                //set value in resultObj
                PropertyInfo propResult = resultObj.GetType().GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance);
                if (propResult != null && propResult.CanWrite)
                {
                    propResult.SetValue(resultObj, propValue, null);
                }
            }
            catch (Exception ex)
            {  
                // do something with Ex
            }
        }
    }

-1

您可以尝试以下方法:

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

每个数组一旦实现IEnumerable接口

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.