相同字段的模型映射

这个博客介绍了如何使用C#的表达式树(Expression Trees)来创建一个泛型类`ExpressionGenericMapper<TIn, TOut>`,用于实现不同对象之间的属性和字段映射。在类的静态构造函数中,遍历输入类型和输出类型的属性和字段,检查它们是否可写,并尝试创建成员绑定,处理类型不匹配的异常。`MapperTo`方法则提供了将单个对象或对象列表从TIn类型转换为TOut类型的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DataSync
{
    public static class ExpressionGenericMapper<TIn, TOut>
    {
        private static readonly BindingFlags flag = BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance;
        private static readonly Func<TIn, TOut> _func = null;
        static ExpressionGenericMapper()
        {

            Type tin = typeof(TIn);
            Type tout = typeof(TOut);
            MemberExpression property;//要访问的字段或属性
            MemberBinding memberBinding;//创建新对象成员
            ParameterExpression parameterExpression = Expression.Parameter(tin, "p");//参数表达式
            List<MemberBinding> memberBindingList = new List<MemberBinding>();//用于创建新对象的成员(属性或字段)
            PropertyInfo propertyInfo;
            foreach (var outPropertyInfo in tout.GetProperties())
            {
                propertyInfo = tin.GetProperty(outPropertyInfo.Name, flag);
                if (propertyInfo == null)
                    continue;
                if (!propertyInfo.CanWrite)
                    continue;
                //if (item.PropertyType.Name != propertyInfo.PropertyType.Name)
                //{  }
                property = Expression.Property(parameterExpression, propertyInfo);
                try
                {
                    memberBinding = Expression.Bind(outPropertyInfo, property);
                }
                catch (Exception ex)
                {
                    memberBinding = null;
                    LogHelper.Error(ex);
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.Append("字段").Append(propertyInfo.Name).Append("类型不一致:");
                    stringBuilder.Append("输入类型:").Append(propertyInfo.Name);
                    stringBuilder.Append("输出类型:").Append(outPropertyInfo.Name);
                    throw new Exception(stringBuilder.ToString());
                }
                memberBindingList.Add(memberBinding);
            }
            FieldInfo fieldInfo;
            foreach (var item in tout.GetFields())
            {
                fieldInfo = tin.GetField(item.Name, flag);
                if (fieldInfo == null)
                    continue;
                property = Expression.Field(parameterExpression, fieldInfo);
                memberBinding = Expression.Bind(item, property);
                memberBindingList.Add(memberBinding);
            }
            MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(tout), memberBindingList.ToArray());
            Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
            {
                parameterExpression
            });
            _func = lambda.Compile();//拼装是一次性的

        }
        public static TOut MapperTo(TIn obj)
        {
            if (obj == null)
                return default;
            return _func(obj);
        }
        public static List<TOut> MapperTo(List<TIn> list)
        {
            if (list == null || list.Count < 1)
                return null;
            List<TOut> temp = new List<TOut>();
            list.ForEach(obj =>
            {
                temp.Add(_func(obj));
            });
            return temp;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值