C# 利用反射复制同名属性
🏷️ C#
下面示例代码仅支持基本类型,T[]
和 List<T>
类型的同名属性转换。
csharp
/// <summary>
/// 复制同名属性
/// </summary>
/// <typeparam name="D">目标类型</typeparam>
/// <typeparam name="S">源类型</typeparam>
/// <param name="s">源数据</param>
/// <returns></returns>
public static D Mapper<D, S>(S s)
{
D d = Activator.CreateInstance<D>();
try
{
Mapper(s, typeof(S), d, typeof(D));
}
catch (Exception ex)
{
throw ex;
}
return d;
}
/// <summary>
/// 复制同名属性
/// </summary>
/// <param name="s">源数据</param>
/// <param name="typeS">源类型</param>
/// <param name="d">目标数据</param>
/// <param name="typeD">目标类型</param>
private static void Mapper(object s, Type typeS, object d, Type typeD)
{
if (s == null)
{
d = null;
return;
}
foreach (PropertyInfo sp in typeS.GetProperties())//获得类型的属性字段
{
foreach (PropertyInfo dp in typeD.GetProperties())
{
// 判断属性名是否相同
if (dp.Name == sp.Name)
{
if (dp.PropertyType == sp.PropertyType)
{
dp.SetValue(d, sp.GetValue(s), null);//获得 s 对象属性的值复制给 d 对象的属性
}
else if (dp.PropertyType.FullName.IndexOf("System.Collections.Generic.List") == 0
&& sp.PropertyType.FullName.IndexOf("System.Collections.Generic.List") == 0)
{
// 属性名相同的列表且类型不一致时,同样的复制相同属性的值到目标类型实例
if (sp.GetValue(s) == null)
{
dp.SetValue(d, null, null);
}
else
{
int count = Convert.ToInt32(sp.PropertyType.GetProperty("Count").GetValue(sp.GetValue(s)));
Type itemTypeS = sp.PropertyType.GenericTypeArguments[0];
Type itemTypeD = dp.PropertyType.GenericTypeArguments[0];
object lstD = Activator.CreateInstance(dp.PropertyType); ;
for (int i = 0; i < count; i++)
{
object itemD = Activator.CreateInstance(itemTypeD);
Mapper(sp.PropertyType.GetProperty("Item").GetValue(sp.GetValue(s), new object[] { i }), itemTypeS, itemD, itemTypeD);
dp.PropertyType.GetMethod("Add").Invoke(lstD, new object[] { itemD });
}
dp.SetValue(d, lstD, null);
}
}
else if (dp.PropertyType.BaseType == typeof(Array) && sp.PropertyType.BaseType == typeof(Array))
{
if (sp.GetValue(s) == null)
{
dp.SetValue(d, null, null);
}
else
{
int length = Convert.ToInt32(sp.PropertyType.GetProperty("Length").GetValue(sp.GetValue(s)));
Type itemTypeS = sp.PropertyType.GetElementType();
Type itemTypeD = dp.PropertyType.GetElementType();
object arrD = Array.CreateInstance(itemTypeD, length);
for (int i = 0; i < length; i++)
{
object itemD = Activator.CreateInstance(itemTypeD);
Mapper(sp.PropertyType.GetMethod("GetValue", new Type[] { typeof(int) }).Invoke(sp.GetValue(s), new object[] { i }), itemTypeS, itemD, itemTypeD);
dp.PropertyType.GetMethod("SetValue", new Type[2] { itemTypeD, typeof(int) }).Invoke(arrD, new object[] { itemD, i });
}
dp.SetValue(d, arrD, null);
}
}
else if (!dp.PropertyType.IsPrimitive && !sp.PropertyType.IsPrimitive)
{
object objD = Activator.CreateInstance(dp.PropertyType);
Mapper(sp.GetValue(s), sp.PropertyType, objD, dp.PropertyType);
dp.SetValue(d, objD, null);
}
}
}
}
}