C# 對象類型映射轉換方法總結,表達式目錄樹實現高效轉換

       開發過程中經常會遇到對象類型之間的轉換映射,例如Model和ViewModel之間的映射綁定,下面總結幾種常見的轉換方式。事先準備兩個類:
CheckFileCheckFileModel


 	public class CheckFile
    {
        public string Id { get; set; }
        public string FileTitle { get; set; }
        public string Author { get; set; }
        public DateTime? CreatTime;
    }
    
    public class CheckFileModel
    {
        public string Id { get; set; }
        public string FileTitle { get; set; }
        public string Author { get; set; }
        public DateTime? CreatTime;
        public string Source { get; set; }
    }

1. 強類型賦值綁定

    
    CheckFile checkFile = new CheckFile
    {
        Id = "123",
        FileTitle = "對象類型轉換映射",
        Author = "張三",
        CreatTime = DateTime.Now
    };

	CheckFileModel fileModel = new CheckFileModel
    {
        Id = checkFile.Id,
        FileTitle = checkFile.FileTitle,
        Author = checkFile.Author,
        CreatTime = checkFile.CreatTime
    };
    

2. 泛型+反射


	  /// <summary>
      /// 泛型+反射
      /// </summary>
      /// <typeparam name="TOut"></typeparam>
      /// <typeparam name="TIn"></typeparam>
      /// <param name="objIn"></param>
      /// <returns></returns>
      public static TOut TypeConvert<TOut, TIn>(TIn objIn)
      {
          Type tOut = typeof(TOut);
          Type tIn = typeof(TIn);
          TOut outModel = Activator.CreateInstance<TOut>();

          // 屬性賦值
          foreach (var prop in tOut.GetProperties())
          {
              var propInfo = tIn.GetProperty(prop.Name);
              if (propInfo != null)
              {
                  var inValue = propInfo.GetValue(objIn);
                  prop.SetValue(outModel, inValue);
              }
          }

          // 字段賦值
          foreach (var field in tOut.GetFields())
          {
              var fieldInfo = tIn.GetField(field.Name);
              if (fieldInfo != null)
              {
                  var inValue = fieldInfo.GetValue(objIn);
                  field.SetValue(outModel, inValue);
              }
          }
          return outModel;
      }
    

3. Json序列化轉換


      /// <summary>
      /// Json序列化轉換
      /// </summary>
      /// <typeparam name="TOut"></typeparam>
      /// <typeparam name="TIn"></typeparam>
      /// <param name="objIn"></param>
      /// <returns></returns>
      public static TOut SerializeConvert<TOut, TIn>(TIn objIn)
      {
          string inString = JsonConvert.SerializeObject(objIn);
          TOut outModel = JsonConvert.DeserializeObject<TOut>(inString);
          return outModel;
      }
      

4. AutoMapper序列化轉換


      /// <summary>
      /// AutoMapper序列化轉換
      /// </summary>
      /// <typeparam name="TOut"></typeparam>
      /// <typeparam name="TIn"></typeparam>
      /// <param name="objIn"></param>
      /// <returns></returns>
      public static TOut AutoMapperConvert<TOut, TIn>(TIn objIn)
      {
          // 初始化
          Mapper.Initialize(n => n.CreateMap<TIn, TOut>());

          TOut outModel = Mapper.Map<TIn, TOut>(objIn);
          return outModel;
      }
        

5. Expression表達式目錄樹轉換


      /// <summary>
      /// Expression表達式目錄樹轉換
      /// </summary>
      /// <typeparam name="TOut"></typeparam>
      /// <typeparam name="TIn"></typeparam>
      /// <param name="objIn"></param>
      /// <returns></returns>
      public static TOut ExpressionConvert<TOut, TIn>(TIn objIn)
      {
          ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
          List<MemberBinding> memberBindingList = new List<MemberBinding>();

          // 綁定屬性
          PropertyInfo[] outPropertyInfos = typeof(TOut).GetProperties();
          foreach (var prop in outPropertyInfos)
          {
              PropertyInfo inPropertyInfo = typeof(TIn).GetProperty(prop.Name);
              if (inPropertyInfo != null)
              {
                  MemberExpression property = Expression.Property(parameterExpression, inPropertyInfo);
                  MemberBinding memberBinding = Expression.Bind(prop, property);
                  memberBindingList.Add(memberBinding);
              }
          }

          // 綁定字段
          FieldInfo[] outFieldInfos = typeof(TOut).GetFields();
          foreach (var field in outFieldInfos)
          {
              FieldInfo inFieldInfo = typeof(TIn).GetField(field.Name);
              if (inFieldInfo != null)
              {
                  MemberExpression fieldInfo = Expression.Field(parameterExpression, inFieldInfo);
                  MemberBinding memberBinding = Expression.Bind(field, fieldInfo);
                  memberBindingList.Add(memberBinding);
              }
          }

          MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
          Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
          {
              parameterExpression
          });
          Func<TIn, TOut> func = lambda.Compile();
          return func.Invoke(objIn);
      }
	  
	  //----------------------------------------------------------
	  // 等價於構造一個下面的表達式
      Expression<Func<CheckFile, CheckFileModel>> lambda = p => new CheckFileModel
      {
          Id = p.Id,
          FileTitle = p.FileTitle,
          Author = p.Author,
          CreatTime = p.CreatTime
      };
      lambda.Compile().Invoke(checkFile);

       

表達式目錄樹

在這裏插入圖片描述
每個矩形框爲一個節點(表達式類型),節點有多種類型,對於而這個 a*b+2 的幾個節點:

  • a,b是參數,類型爲ParameterExpression
  • +,*,爲二元運符,類型爲BinaryExpression
  • 2爲常量,類型爲ConstantExpression

	Expression<Func<int, int, int>> exp1 = (a, b) => a * b+2;

	//兩個參數
	ParameterExpression a = Expression.Parameter(typeof(int), "a");
	ParameterExpression b = Expression.Parameter(typeof(int), "b"); 
	
	//求積
	BinaryExpression Multi=Expression.Multiply(a,b); 
	
	//常量
	ConstantExpression x2 = Expression.Constant(2); 
	
	//求和
	BinaryExpression Add = Expression.Add(Multi, x2); 
	
	//創建一個表示lambda表達式的對象
	LambdaExpression lexp = Expression.Lambda<Func<int, int, int>>(Add, a, b); 

	//查看表達式
	Console.WriteLine(lexp.ToString());
	
	//簡單使用
	Expression<Func<int, int, int>> lexp = Expression.Lambda<Func<int, int, int>>(Add, a, b);
	Func<int, int, int> fun = lexp.Compile();
	Console.WriteLine(fun(3,5));
	

END
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章