如何获取列表中每个字符串的值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);
}
在您进一步阅读之前,我建议您查看一下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));
}
}
推荐阅读:如何使用反射检查和实例化泛型类型
另一个选择可以结合使用反射和序列化。
- 将源对象序列化为流
- 反序列化源对象的新副本(新对象将不共享原始源的任何引用)
- 从源克隆复制属性到目标使用:
dataBasePropInfo.SetValue(dataBaseObject, modelPropInfo.GetValue(modelObject));