通过表达式目录树拼装lambda表达式,来实现两个类型的复制

Posted xiaojunwu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过表达式目录树拼装lambda表达式,来实现两个类型的复制相关的知识,希望对你有一定的参考价值。

一、下面的方法实现两个类型间的值复制

    /// <summary>  
    /// 交换两个类型的属性(复制)  
    /// </summary>  
    /// <typeparam name="Tin"></typeparam>  
    /// <typeparam name="Tout"></typeparam>  
    public static class ExpressionCopy<Tin, Tout>  
    {  
        public static Tout Excharnge(Tin tin)  
        {  
            ParameterExpression experssionin = Expression.Parameter(typeof(Tin), "tModel");//创建实例  
            List<MemberBinding> memberList = new List<MemberBinding>();//通过绑定用的  
            foreach (var item in typeof(Tout).GetFields())//遍历所有的共有字段  
            {  
                FieldInfo field = typeof(Tin).GetField(item.Name.GetPropertyRemark(typeof(Tout), 1));  
                if (field != null)  
                {  
                    MemberExpression member = Expression.Field(experssionin, field);  
                    MemberBinding binding = Expression.Bind(item, member);  
                    memberList.Add(binding);  
                }  
            }  
    
            foreach (var item in typeof(Tout).GetProperties())//遍历属性  
            {  
                PropertyInfo pro = typeof(Tin).GetProperty(item.Name.GetPropertyRemark(typeof(Tout), 2));//判断属性是否存在  
                if (pro != null)  
                {  
                    MemberExpression proper = Expression.Property(experssionin, pro);  
                    MemberBinding binding = Expression.Bind(item, proper);  
                    memberList.Add(binding);  
                }  
    
            }  
    
            MemberInitExpression init = Expression.MemberInit(Expression.New(typeof(Tout)), memberList.ToArray());//初始化绑定新成员  
            Expression<Func<Tin, Tout>> lambda = Expression.Lambda<Func<Tin, Tout>>(init, new ParameterExpression[]  
            {   
            experssionin  
            });  
            return lambda.Compile().Invoke(tin);  
        }  
    }  

 

二、声明特性为了防止当要复制的属性字段不一致

/// <summary>  
    /// 特性  
    /// </summary>  
    public class GetRemarkAttribute : Attribute  
    {  
        public GetRemarkAttribute(string name)  
        {  
            this._remark = name;  
        }  
        private string _remark;  
        public string GetRemark()  
        {  
            return _remark;  
        }  
    }  

 

三、通过反射为string类型添加一个扩展方法,来获取特性的值

 1 public static class GetRemark  
 2    {  
 3        /// <summary>  
 4        /// 通过反射获得特性  
 5        /// </summary>  
 6        /// <param name="values">字段属性名称</param>  
 7        /// <param name="type">类型</param>  
 8        /// <param name="parameter">参数1为字段2为属性</param>  
 9        /// <returns></returns>  
10        public static string GetPropertyRemark(this string values, Type type, int parameter)  
11        {  
12            if (parameter == 1)  
13            {  
14                FieldInfo propperty = type.GetField(values);  
15     
16                if (propperty.IsDefined(typeof(GetRemarkAttribute)))  
17                {  
18                    GetRemarkAttribute remark = (GetRemarkAttribute)propperty.GetCustomAttribute(typeof(GetRemarkAttribute));  
19                    return remark.GetRemark();  
20                }  
21     
22            }  
23            else  
24            {  
25                PropertyInfo propperty = type.GetProperty(values);  
26     
27                if (propperty.IsDefined(typeof(GetRemarkAttribute)))  
28                {  
29                    GetRemarkAttribute remark = (GetRemarkAttribute)propperty.GetCustomAttribute(typeof(GetRemarkAttribute));  
30                    return remark.GetRemark();  
31                }  
32     
33            }  
34            return values;  
35     
36        }  
37    }  

 

四、下面就是实际操作调用

 1 public class OldPersoninfo  
 2     {  
 3         public int Id { get; set; }  
 4         public string Name { get; set; }  
 5         public string Type { get; set; }  
 6         public OldPersoninfo()  
 7         {  
 8             Id = 2;  
 9             Name = "测试";  
10             Type = "非常类额";  
11         }  
12     }  
13     public class NewPersoninfo  
14     {  
15         public int Id { get; set; }  
16        // [GetRemark("Name")]  
17         public string newName { get; set; }  
18         //[GetRemark("Type")]  
19         public string newType { get; set; }  
20     }  
21  
22 
23 private void test_Load(object sender, EventArgs e)  
24        {  
25            OldPersoninfo old = new OldPersoninfo();  
26            NewPersoninfo newPersoninfo = ExpressionCopy<OldPersoninfo, NewPersoninfo>.Excharnge(old);  
27            MessageBox.Show(newPersoninfo.newType);  
28        }  

 

以上是关于通过表达式目录树拼装lambda表达式,来实现两个类型的复制的主要内容,如果未能解决你的问题,请参考以下文章

Lambda创建表达式目录树

通过 lambda 表达式实现具有两个抽象方法的接口

Lambda表达式树构建(上)

递归 lambda 表达式在 C# 中遍历树

lambda查询

表达式目录树Expression