开发代码中遇到两个对象具有很多相同的属性名称并且类型一致,为了减少编码和提高开发效率,利用反射原理来解析某个对象中的属性值拷贝到另一个对象与之对应的属性中。
可以查看之前反射原理的文章 http://blog.csdn.net/yhz815/article/details/9379873
今天整理出两个方法:
方法一:【拷贝所有属性和公共字段】代码如下
/// <summary>
/// Copy Propertys and Fileds
/// 拷贝属性和公共字段
/// </summary>
/// <typeparam name="T"> </typeparam>
/// <param name="source"></param>
/// <param name="target"></param>
public static void CopyToAll<T>(this object source, T target) where T : class
{
if (source == null)
{
return;
}
if (target == null)
{
throw new ApplicationException("target 未实例化!");
}
var properties = target.GetType().GetProperties();
foreach (var targetPro in properties)
{
try
{
//判断源对象是否存在与目标属性名字对应的源属性
if (source.GetType().GetProperty(targetPro.Name) == null)
{
continue;
}
//数据类型不相等
if (targetPro.PropertyType.FullName != source.GetType().GetProperty(targetPro.Name).PropertyType.FullName)
{
continue;
}
var propertyValue = source.GetType().GetProperty(targetPro.Name).GetValue(source, null);
if (propertyValue != null)
{
target.GetType().InvokeMember(targetPro.Name, BindingFlags.SetProperty, null, target, new object[] { propertyValue });
}
}
catch (Exception ex)
{
}
}
//返回所有公共字段
var targetFields = target.GetType().GetFields();
foreach (var filed in targetFields)
{
try
{
var tfield = source.GetType().GetField(filed.Name);
if (null == tfield)
{
//如果源对象中不包含这个公共字段则不处理
continue;
}
//类型不一致不处理
if (filed.FieldType.FullName != tfield.FieldType.FullName)
{
continue;
} var fieldValue = tfield.GetValue(source);
if (fieldValue != null)
{
target.GetType().InvokeMember(filed.Name, BindingFlags.SetField, null, target, new object[] { fieldValue });
}
}
catch (Exception ex)
{
}
}
}
方法二:【拷贝简单类型的属性和公共字段】
/// <summary>
/// Copy Simple Property and Fileds
/// 拷贝简单属性和公共字段
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="target"></param>
public static void CopyTo<T>(this object source, T target) where T : class
{
if (source == null)
{
return;
}
if (target == null)
{
throw new ApplicationException("target 未实例化!");
}
var properties = target.GetType().GetProperties();
foreach (var targetPro in properties)
{
try
{
//判断源对象是否存在与目标属性名字对应的源属性
if (source.GetType().GetProperty(targetPro.Name) == null)
{
continue;
}
//判断是否枚举集合
if (targetPro.PropertyType.IsGenericType && targetPro.PropertyType.GetGenericArguments()[0].IsEnum)
{
continue;
}
// 判断是否数组
else if (targetPro.PropertyType.IsArray)
{
continue;
}
// 判断是否IList
else if (targetPro.PropertyType.IsGenericType && targetPro.PropertyType.GetInterface("System.Collections.IEnumerable") != null)
{
continue;
}
var propertyValue = source.GetType().GetProperty(targetPro.Name).GetValue(source, null);
if (propertyValue != null)
{
if (propertyValue.GetType().IsEnum)
{
continue;
}
target.GetType().InvokeMember(targetPro.Name, BindingFlags.SetProperty, null, target, new object[] { propertyValue });
}
}
catch (Exception ex)
{
}
}
//返回所有公共字段
var targetFields = target.GetType().GetFields();
foreach (var filed in targetFields)
{
try
{
var tfield = source.GetType().GetField(filed.Name);
if (null == tfield)
{
//如果源对象中不包含这个公共字段则不处理
continue;
}
//类型不一致不处理
if (filed.FieldType.FullName != tfield.FieldType.FullName)
{
continue;
}
var fieldValue = tfield.GetValue(source);
if (fieldValue != null)
{
target.GetType().InvokeMember(filed.Name, BindingFlags.SetField, null, target, new object[] { fieldValue });
}
}
catch (Exception ex)
{
}
}
}
调用方法如下:
using DataConvert.Models;
using DataConvertCommon;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DataConverter
{
class Program
{
static void Main(string[] args)
{
try
{
User user = new User();
user.Name = "Martin";
user.Age = 26;
user.ArrayInt = new int[] { 2, 6 };
user.ObjList = new System.Collections.ObjectModel.ObservableCollection<object>() { "This is a test", 0, "haha" };
user.StrList = new List<string>() { "str1", "str2" };
user.State = UserState.Modify;
user.iType = 10;
user.Str = "Good";
Print(user);
UserTest test = new UserTest();
user.CopyToAll<UserTest>(test);
Print(test);
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
static void Print(object obj)
{
var propertyInfos = obj.GetType().GetProperties();
foreach (var item in propertyInfos)
{
Console.WriteLine(string.Format("{0}: {1}",item.Name,item.GetValue(obj,null)));
}
}
}
}
至于User类和UserTest类 我此处就不贴代码了,大家可以根据自己的需要定义类型来尝试一下。
如果有写错的地方,欢迎指正!