从未知对象获取属性和值

Posted

技术标签:

【中文标题】从未知对象获取属性和值【英文标题】:Get properties and values from unknown object 【发布时间】:2010-11-10 13:11:02 【问题描述】:

php 的世界开始,我决定尝试 C#。我已经进行了搜索,但似乎找不到如何做到这一点的答案。

$object = new Object();

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

foreach($vars as $var)

    doSomething($object->$var);

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

任何帮助将不胜感激。

【问题讨论】:

附带说明:在列表中包含不同类型的对象(没有公共基类或接口)不是一种好的编程风格,至少在 c# 中不是。 【参考方案1】:

应该这样做:

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

【讨论】:

@jonathan System.Reflection 命名空间 实际上不需要从数组创建列表,只需PropertyInfo[] props = input.GetType().GetProperties(); 您想使用 Newtonsoft.Json.JsonConvert 更新 2017 年的答案吗? @clone 这是一种完全不同的方式。如果您认为这是一种有效的方法,您应该发布答案 @Jonesopolis 如何从dynamic 获取属性,而不先将其转换为object,然后按照我的答案进行操作?【参考方案2】:
void Test()
    var obj = newa="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】:

是的,反射将是要走的路。首先,您将获得Type,它表示列表中实例的类型(在运行时)。您可以通过拨打GetType method on Object 来完成此操作。因为它在Object 类上,它可以被.NET 中的每个 对象调用,因为所有类型都派生自Object(well, 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 运算符来帮助确定哪个您在运行时使用的基类/接口)。

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

【讨论】:

【参考方案4】:

嗯,在 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));

【讨论】:

【参考方案5】:

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

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

【讨论】:

【参考方案6】:

使用 Linq 的单行解决方案...

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

【讨论】:

【参考方案7】:

您可以使用GetType - GetProperties - Linq Foreach

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

【讨论】:

【参考方案8】:

这是我用来将IEnumerable&lt;T&gt; 转换为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&lt;T&gt;,例如:

public class Car

    string Make  get; set; 
    int YearOfManufacture get; set; 

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

制作(字符串) YearOfManufacture (int)

List&lt;Car&gt; 中的每一项都包含一行

【讨论】:

【参考方案9】:

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

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

【讨论】:

【参考方案10】:

我还没有发现这个可以工作,比如应用程序对象。然而,我已经成功了

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

string rval = serializer.Serialize(myAppObj);

【讨论】:

如果可以避免,请不要使用 JavaScriptSerializer。 There are great many reasons.【参考方案11】:

你可以试试这个:

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

一旦每个数组都实现了 IEnumerable 接口

【讨论】:

【参考方案12】:
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;

【讨论】:

【参考方案13】:
    /// 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
            
        
    

【讨论】:

以上是关于从未知对象获取属性和值的主要内容,如果未能解决你的问题,请参考以下文章

LINQ:获取包含具有特定名称和值的属性的数组中的对象

如何从未指定的对象中获取属性?

从核心数据读取时获取属性名称和值

java反射获取属性值

ConfigurationManager.Read 从未知来源读取

js动态为对象添加属性和方法