从未知对象获取属性和值。

时间:2022-09-07 10:54:53

From the world of PHP I have decided to give C# a go. I've had a search but can't seem to find the answer of how to do the equivalent to this.

在PHP的世界里,我决定给c# a。我有过一次搜索,但似乎找不到如何做这个的答案。

$object = new Object();

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

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

I basically have a List of an object. The object could be one of three different types and will have a set of public properties. I want to be able to get a list of the properties for the object, loop over them and then write them out to a file. I'm thinking this has something to do with c# reflection but it's all new to me.

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

Any help would be greatly appreciated.

非常感谢您的帮助。

10 个解决方案

#1


216  

This should do it:

这应该这样做:

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
}

#2


17  

Yes, Reflection would be the way to go. First, you would get the Type that represents the type (at runtime) of the instance in the list. You can do this by calling the GetType method on Object. Because it is on the Object class, it's callable by every object in .NET, as all types derive from Object (well, technically, not everything, but that's not important here).

是的,思考是前进的道路。首先,您将得到表示列表中实例的类型(在运行时)的类型。您可以通过在对象上调用GetType方法来实现这一点。因为它在对象类上,所以。net中的每个对象都可以调用它,因为所有类型都来自对象(从技术上来说,不是所有的东西,但在这里并不重要)。

Once you have the Type instance, you can call the GetProperties method to get the PropertyInfo instances which represent the run-time informationa about the properties on the Type.

一旦您拥有了类型实例,您就可以调用GetProperties方法来获取表示运行时信息的PropertyInfo实例,该实例描述了类型上的属性。

Note, you can use the overloads of GetProperties to help classify which properties you retrieve.

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

From there, you would just write the information out to a file.

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

Your code above, translated, would be:

你上面的代码,翻译过来就是:

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

Note that if you want method information or field information, you would have to call the one of the overloads of the GetMethods or GetFields methods respectively.

注意,如果您想要方法信息或字段信息,则必须分别调用GetMethods或GetFields方法的重载。

Also note, it's one thing to list out the members to a file, but you shouldn't use this information to drive logic based on property sets.

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

Assuming you have control over the implementations of the types, you should derive from a common base class or implement a common interface and make the calls on those (you can use the as or is operator to help determine which base class/interface you are working with at runtime).

假设您已经控制了类型的实现,您应该从一个公共基类派生出来,或者实现一个公共接口,并对这些实现进行调用(您可以使用as或者是操作符来帮助确定您在运行时使用的基类/接口)。

However, if you don't control these type definitions and have to drive logic based on pattern matching, then that's fine.

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

#3


7  

well, in C# it's similar. Here's one of the simplest examples (only for public properties):

在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


6  

To get specific property value from property name

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

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

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

to access property value of Name from string name of property

从属性的字符串名称访问名称的属性值。

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

#5


6  

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

#6


4  

You can use GetType - GetProperties - Linq Foreach:

您可以使用GetType - GetProperties - Linq Foreach:

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

#7


2  

Here's something I use to transform an IEnumerable<T> into a DataTable that contains columns representing T's properties, with one row for each item in the IEnumerable:

这里有一些我用来将IEnumerable的 转换为包含表示T属性的列的DataTable,其中一行对应于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;
}

This is "somewhat" overcomplicated, but it's actually quite good for seeing what the outcome is, as you can give it a List<T> of, for example:

这有点过于复杂了,但它实际上很好地看到了结果是什么,你可以给它一个列表 ,例如:

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

And you'll be returned a DataTable with the structure:

你将会得到一个与结构的数据表:

Make (string)
YearOfManufacture (int)

使(字符串)YearOfManufacture(int)

With one row per item in your List<Car>

在您的列表中每一项的每一项 <汽车> 。

#8


1  

This example trims all the string properties of an object.

这个示例对一个对象的所有字符串属性进行了测试。

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

#9


0  

I haven't found this to work on, say Application objects. I have however had success with

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

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

string rval = serializer.Serialize(myAppObj);

#10


0  

You can try this:

你可以试试这个:

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

Once every array implements IEnumerable interface

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

#1


216  

This should do it:

这应该这样做:

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
}

#2


17  

Yes, Reflection would be the way to go. First, you would get the Type that represents the type (at runtime) of the instance in the list. You can do this by calling the GetType method on Object. Because it is on the Object class, it's callable by every object in .NET, as all types derive from Object (well, technically, not everything, but that's not important here).

是的,思考是前进的道路。首先,您将得到表示列表中实例的类型(在运行时)的类型。您可以通过在对象上调用GetType方法来实现这一点。因为它在对象类上,所以。net中的每个对象都可以调用它,因为所有类型都来自对象(从技术上来说,不是所有的东西,但在这里并不重要)。

Once you have the Type instance, you can call the GetProperties method to get the PropertyInfo instances which represent the run-time informationa about the properties on the Type.

一旦您拥有了类型实例,您就可以调用GetProperties方法来获取表示运行时信息的PropertyInfo实例,该实例描述了类型上的属性。

Note, you can use the overloads of GetProperties to help classify which properties you retrieve.

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

From there, you would just write the information out to a file.

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

Your code above, translated, would be:

你上面的代码,翻译过来就是:

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

Note that if you want method information or field information, you would have to call the one of the overloads of the GetMethods or GetFields methods respectively.

注意,如果您想要方法信息或字段信息,则必须分别调用GetMethods或GetFields方法的重载。

Also note, it's one thing to list out the members to a file, but you shouldn't use this information to drive logic based on property sets.

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

Assuming you have control over the implementations of the types, you should derive from a common base class or implement a common interface and make the calls on those (you can use the as or is operator to help determine which base class/interface you are working with at runtime).

假设您已经控制了类型的实现,您应该从一个公共基类派生出来,或者实现一个公共接口,并对这些实现进行调用(您可以使用as或者是操作符来帮助确定您在运行时使用的基类/接口)。

However, if you don't control these type definitions and have to drive logic based on pattern matching, then that's fine.

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

#3


7  

well, in C# it's similar. Here's one of the simplest examples (only for public properties):

在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


6  

To get specific property value from property name

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

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

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

to access property value of Name from string name of property

从属性的字符串名称访问名称的属性值。

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

#5


6  

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

#6


4  

You can use GetType - GetProperties - Linq Foreach:

您可以使用GetType - GetProperties - Linq Foreach:

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

#7


2  

Here's something I use to transform an IEnumerable<T> into a DataTable that contains columns representing T's properties, with one row for each item in the IEnumerable:

这里有一些我用来将IEnumerable的 转换为包含表示T属性的列的DataTable,其中一行对应于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;
}

This is "somewhat" overcomplicated, but it's actually quite good for seeing what the outcome is, as you can give it a List<T> of, for example:

这有点过于复杂了,但它实际上很好地看到了结果是什么,你可以给它一个列表 ,例如:

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

And you'll be returned a DataTable with the structure:

你将会得到一个与结构的数据表:

Make (string)
YearOfManufacture (int)

使(字符串)YearOfManufacture(int)

With one row per item in your List<Car>

在您的列表中每一项的每一项 <汽车> 。

#8


1  

This example trims all the string properties of an object.

这个示例对一个对象的所有字符串属性进行了测试。

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

#9


0  

I haven't found this to work on, say Application objects. I have however had success with

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

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

string rval = serializer.Serialize(myAppObj);

#10


0  

You can try this:

你可以试试这个:

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

Once every array implements IEnumerable interface

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