如何获取列表中每个字符串的值c#中使用反射

本文关键字:string 反射 何获取 获取 列表 字符串 | 更新日期: 2023-09-27 18:14:44

我想用模型对象值更新数据库对象我如何获得modelObject内属性的值,这是一个列表?

想象一个这样的对象

public class Worker{
     public string Id { get; set; }
     public bool GoodPerson { get; set; }
     public bool Wise { get; set; }
     public List<string> Formation { get; set; }
}

我不知道如何从Formation属性中获得值,所以我如何才能将信息属性中编辑的值反映到我的dataBaseObject中,你能帮助我吗?

如何使用反射来反映这些更改?

public static void UpdateObjectFrom(this object modelObject, object dataBaseObject, string[] excludedProperties = null)
        {
            //WHAT IF THE modelObject is now List<string> ?????, how do i pass the values of modelObject for the dataBaseObject List<string> object

            Type modelObjectType = modelObject.GetType();
            Type dataBaseObjectType = dataBaseObject.GetType();
            PropertyInfo[] modelProperties = modelObjectType.GetProperties();
            PropertyInfo[] dataBaseProperties = dataBaseObjectType.GetProperties();
            if (excludedProperties != null)
            {
                dataBaseProperties = dataBaseProperties.Where(x => !excludedProperties.Contains(x.Name)).ToArray();
            }
            foreach (PropertyInfo dataBasePropInfo in dataBaseProperties)
            {
                if (HasSimpleType(dataBasePropInfo.PropertyType) || dataBasePropInfo.PropertyType.IsGenericType && dataBasePropInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    PropertyInfo modelPropInfo = modelObjectType.GetProperty(dataBasePropInfo.Name);
                    dataBasePropInfo.SetValue(dataBaseObject, modelPropInfo.GetValue(modelObject));
                }
                else if (dataBasePropInfo.PropertyType.IsGenericType)
                {
                    UpdateObjectFrom(dataBasePropInfo.GetValue(dataBaseObject, null), modelObjectType.GetProperty(dataBasePropInfo.Name).GetValue(modelObject, null));
                }
                else if (dataBasePropInfo.PropertyType.IsClass && !dataBasePropInfo.PropertyType.FullName.StartsWith("System."))
                {
                    UpdateObjectFrom(dataBasePropInfo.GetValue(dataBaseObject, null), modelObjectType.GetProperty(dataBasePropInfo.Name).GetValue(modelObject, null));
                }
            }
        }
        private static bool HasSimpleType(Type tipo)
        {
            return tipo.IsPrimitive || tipo == typeof(string) || tipo.IsEnum || tipo == typeof(Decimal) || tipo == typeof(DateTime);
        }

如何获取列表中每个字符串的值<string>c#中使用反射

在您进一步阅读之前,我建议您查看一下AutoMapper。AutoMapper旨在将数据从一种类型映射到另一种类型。在我看来,这就是你想要达到的目的。

需要注意的是,AutoMapper不会对列表执行深度复制。因此,如果您修改源对象上的列表,它将影响目标对象上的列表。

浅复制是直接的,只是直接复制列表,就像你对原始类型和可空类型一样。

代码中需要考虑的其他事项。您检查的是属性名,而不是两个对象的类型。如果int Id在一个班级而string Id在另一个班级呢?

如果你必须有一个列表的深度拷贝,它会变得有点复杂。但这是我想到的(注意:这不是一个真正的深度复制,因为列表的成员不是克隆的):

else if (dataBasePropInfo.PropertyType.IsGenericType)
{
    var args = dataBasePropInfo.PropertyType.GetGenericArguments();
    var lstType = typeof (List<>).MakeGenericType(args);
    if (lstType.IsAssignableFrom(dataBasePropInfo.PropertyType))
    {
        PropertyInfo modelPropInfo = modelObjectType.GetProperty(dataBasePropInfo.Name);
        var target = Activator.CreateInstance(lstType);
        var source = modelPropInfo.GetValue(modelObject);
        lstType.InvokeMember("AddRange", BindingFlags.InvokeMethod, null, target, new[] {source});
        dataBasePropInfo.SetValue(dataBaseObject, target);
    }
    else
    {
        UpdateObjectFrom(dataBasePropInfo.GetValue(dataBaseObject, null), modelObjectType.GetProperty(dataBasePropInfo.Name).GetValue(modelObject, null));
    }
}

推荐阅读:如何使用反射检查和实例化泛型类型

另一个选择

可以结合使用反射和序列化。

  1. 将源对象序列化为流
  2. 反序列化源对象的新副本(新对象将不共享原始源的任何引用)
  3. 从源克隆复制属性到目标使用:dataBasePropInfo.SetValue(dataBaseObject, modelPropInfo.GetValue(modelObject));