利用反射拷贝对应的属性值到另一个对象中

开发代码中遇到两个对象具有很多相同的属性名称并且类型一致,为了减少编码和提高开发效率,利用反射原理来解析某个对象中的属性值拷贝到另一个对象与之对应的属性中。

可以查看之前反射原理的文章 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类 我此处就不贴代码了,大家可以根据自己的需要定义类型来尝试一下。

如果有写错的地方,欢迎指正!



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值