ChatGPT解决这个技术问题 Extra ChatGPT

从未知对象获取属性和值

在 PHP 的世界里,我决定试一试 C#。我进行了搜索,但似乎无法找到如何做到这一点的答案。

$object = new Object();

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

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

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

任何帮助将不胜感激。

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

C
Cocowalla

这应该这样做:

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 如何在不先将其转换为 object 的情况下从 dynamic 获取属性,然后按照我的回答执行相同的操作?
V
Vo Van Khoa
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);
}

G
Glorfindel

是的,反射将是要走的路。首先,您将获得表示列表中实例类型(在运行时)的 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 运算符来帮助确定哪个基类/您在运行时使用的接口)。

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


f
fguillen

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

v
vicky

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

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

R
Rajnikant

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

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

A
Antonio DB

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

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

R
Rob

下面是我用来将 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:

Make (string) YearOfManufacture (int)

List<Car> 中的每一项


B
Brian Paske

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

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

T
Tim S. Van Haren

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

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

string rval = serializer.Serialize(myAppObj);

如果可以避免,请不要使用 JavaScriptSerializer。 There are great many reasons
P
Pablo Rocha Villagra

你可以试试这个:

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

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


I
Ivan Porta
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;
}

n
namsdp
    /// 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
            }
        }
    }