C# 从未知对象获取属性和值

C# 从未知对象获取属性和值,c#,reflection,C#,Reflection,从PHP的世界来看,我决定尝试一下C。我已经搜索过了,但似乎找不到答案,如何做到这一点 $object = new Object(); $vars = get_class_vars(get_class($object)); foreach($vars as $var) { doSomething($object->$var); } 我基本上有一个对象列表。对象可以是三种不同类型中的一种,并且将具有一组公共属性。我希望能够获得对象的属性列表,循环它们,然后将它们写入文件。 我认

从PHP的世界来看,我决定尝试一下C。我已经搜索过了,但似乎找不到答案,如何做到这一点

$object = new Object();

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

foreach($vars as $var)
{
    doSomething($object->$var);
}
我基本上有一个对象列表。对象可以是三种不同类型中的一种,并且将具有一组公共属性。我希望能够获得对象的属性列表,循环它们,然后将它们写入文件。 我认为这与c#reflection有关,但这对我来说是全新的


任何帮助都将不胜感激。

是的,反思才是最好的选择。首先,您将获得表示列表中实例的类型(在运行时)的。您可以通过调用。因为它位于
对象
类中,所以.NET中的每个对象都可以调用它,因为所有类型都派生自
对象
(,但这在这里并不重要)

拥有
类型
实例后,您可以调用以获取代表有关
类型
上属性的运行时信息a的实例

注意,您可以使用
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);
}
//实例可以是任何类型。
对象o=;
//获取类型。
Type Type=o.GetType();
//获取所有公共实例属性。
//如果要分类,请使用替代
//返回哪些属性。
foreach(type.GetProperties()中的PropertyInfo信息)
{
//对属性信息做些什么。
剂量测定(信息);
}
请注意,如果需要方法信息或字段信息,则必须分别调用或方法的其中一个重载

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

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


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

下面是我用来将
IEnumerable
转换为
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;
}
将返回一个数据表,其结构如下:

制作(字符串)
制造年份(国际)

在你的
列表中,每个项目有一行

那么,在C中,它是相似的。 下面是一个最简单的示例(仅适用于公共财产):

这应该做到:

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
}
Type myType=myObject.GetType();
IList props=新列表(myType.GetProperties());
foreach(PropertyInfo props in props)
{
object propValue=prop.GetValue(myObject,null);
//做有价值的事
}

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

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

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

public class Bike{
public string Name {get;set;}
}

Bike b = new Bike {Name = "MyBike"};
从属性的字符串名称访问名称的属性值

public object GetPropertyValue(string propertyName)
{
//returns value of property Name
return this.GetType().GetProperty(propertyName).GetValue(this, null);
} 
您可以使用GetType-GetProperties-Linq Foreach:


比如说应用程序对象,我还没有发现这一点。然而,我在这方面取得了成功

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

string rval = serializer.Serialize(myAppObj);
您可以尝试以下方法:

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

一旦每个数组实现IEnumerable接口

使用Linq的一行解决方案

var obj=new{Property1:1,Property2:2};
var property1=obj.GetType().GetProperties().First(o=>o.Name==“property1”).GetValue(obj,null);
公共字典目录(对象obj)
{
字典=新字典();
类型objectType=obj.GetType();
IList props=新列表(objectType.GetProperties());
foreach(PropertyInfo props in props)
{
object propValue=prop.GetValue(obj,null);
Add(prop.Name,propValue.ToString());
}
返回字典;
}
///get set value字段位于object to object new(两个对象字段类似)
公共静态void SetValueObjectToObject(对象源Obj、对象结果Obj)
{
IList props=新列表(sourceObj.GetType().GetProperties());
foreach(PropertyInfo props in props)
{
尝试
{
//在sourceObj中获取值
object propValue=prop.GetValue(sourceObj,null);
//在resultObj中设置值
PropertyInfo propResult=resultObj.GetType().GetProperty(prop.Name,BindingFlags.Public | BindingFlags.Instance);
if(propResult!=null&&propResult.CanWrite)
{
SetValue(resultObj,propValue,null);
}
}
捕获(例外情况除外)
{  
//和前男友做点什么
}
}
}

作为旁注:在列表中包含不同类型的对象(没有公共基类或接口)不是一种好的编程风格,至少在c#@jonathan
系统中不是这样。反射
Namespace实际上不需要从数组创建列表,只需
PropertyInfo[]props=input.GetType().GetProperties()
您想使用
Newtonsoft.Json.JsonConvert
?@clone更新2017年的答案吗?这是一种完全不同的方式。如果你认为答案是正确的,你应该发布一个答案approach@Jonesopolis如何从
动态
获取属性,而不首先将其强制转换为
对象
,然后执行与我的回答相同的操作?如果可以避免,请不要使用JavaScriptSerializer。
obj.GetType().GetProperties().ToList().ForEach(p =>{
                                                        //p is each PropertyInfo
                                                        DoSomething(p);
                                                    });
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);
}
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();

string rval = serializer.Serialize(myAppObj);
string[] arr = ((IEnumerable)obj).Cast<object>()
                                 .Select(x => x.ToString())
                                 .ToArray();
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;
}
    /// 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
            }
        }
    }