Featured image of post c# 如何如何自由转换两个沒有继承关系的字段及类型相同的实体模型

c# 如何如何自由转换两个沒有继承关系的字段及类型相同的实体模型

这篇文章我们来总结一 c# 如何如何自由转换两个沒有继承关系的字段及类型相同的实体模型。

首先定义2个实体类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class Person

{
    public string Name { get; set; }

    public int Age { get; set; }

}



public class PersonDto
{
    public string Name { get; set; }

    public int Age { get; set; }

}

1.硬编码手动转换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Person p = new Person()
{

    Age = 10,

   Name = "張三"

};

PersonDto pd = new PersonDto()
{

    Name = p.Name,

    Age = p.Age

};

2.委托实现实体的相互转换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Person p = new Person()

{

    Age = 10,
   Name = "張三"

};

Func<Person, PersonDto> func = c => new PersonDto()
{

    Age = c.Age,

    Name = c.Name
};

PersonDto pd = func(p);

3. 使用AutoMapper完成不同实体的转换

1
2
3
4
5
Person p = new Person() { Age = 10, Name = "張三" };

Mapper.Initialize(m => m.CreateMap<Person, PersonDto>());

PersonDto pd = Mapper.Map<PersonDto>(p);

4.通过反射实现实体的相互转换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/// <summary>

/// 实体映射

/// </summary>

/// <typeparam name="TDestination">目标实体</typeparam>

/// <param name="source">源实体</param>

/// <returns></returns>

public static TDestination MapTo<TDestination>(object source) where TDestination : new()

{
    TDestination dest = new TDestination();//创建目标对象

    foreach (var p in dest.GetType().GetProperties())//獲取源实体所有的属性
    {

        p.SetValue(dest, source.GetType().GetProperty(p.Name)?.GetValue(source));//挨個為目標實體對應字段名進行賦值

    }

 return dest;

}

5. 通过Json反序列化实现实体的相互转换

1
2
3
4
5
首先通过nuget把Newtonsoft.Json引進來,然后coding...

Person p = new Person() { Age = 10, Name = "張三" };

PersonDto pd = JsonConvert.DeserializeObject<PersonDto>(JsonConvert.SerializeObject(p));

6.表达式树实现实体的相互转换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Person p = new Person() { Age = 10, Name = "張三" };

ParameterExpression parameterExpression = Expression.Parameter(typeof(Person), "p");

List<MemberBinding> memberBindingList = new List<MemberBinding>();//表示綁定的類派生自的基類,這些綁定用于對新創建對象的成員進行初始化(vs的注解。太生澀了,我這樣的小白解釋不了,大家將就著看)

foreach (var item in typeof(PersonDto).GetProperties()) //遍歷目標類型的所有屬性

{

    MemberExpression property = Expression.Property(parameterExpression, typeof(Person).GetProperty(item.Name));//獲取到對應的屬性

    MemberBinding memberBinding = Expression.Bind(item, property);//初始化這個屬性

    memberBindingList.Add(memberBinding);

}

foreach (var item in typeof(PersonDto).GetFields())//遍歷目標類型的所有字段

{

    MemberExpression property = Expression.Field(parameterExpression, typeof(Person).GetField(item.Name));//獲取到對應的字段

    MemberBinding memberBinding = Expression.Bind(item, property);//同上

    memberBindingList.Add(memberBinding);

}

MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(PersonDto)), memberBindingList.ToArray());//初始化創建新對象

Expression<Func<Person, PersonDto>> lambda = Expression.Lambda<Func<Person, PersonDto>>(memberInitExpression, parameterExpression);

PersonDto pd = lambda.Compile()(p);

7.表达式树的封裝实现通用实体的相互转换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public static TDestination ExpressionTreeMapper<TSource, TDestination>(TSource source)

{

    ParameterExpression parameterExpression = Expression.Parameter(typeof(TSource), "p");

    List<MemberBinding> memberBindingList = new List<MemberBinding>();//表示綁定的類派生自的基類,這些綁定用于對新創建對象的成員進行初始化(vs的注解。太生澀了,我這樣的小白解釋不了,大家將就著看)

    foreach (var item in typeof(TDestination).GetProperties()) //遍歷目標類型的所有屬性

    {

        MemberExpression property = Expression.Property(parameterExpression, typeof(TSource).GetProperty(item.Name));//獲取到對應的屬性

        MemberBinding memberBinding = Expression.Bind(item, property);//初始化這個屬性

        memberBindingList.Add(memberBinding);

    }

    foreach (var item in typeof(TDestination).GetFields())//遍歷目標類型的所有字段
   {

        MemberExpression property = Expression.Field(parameterExpression, typeof(TSource).GetField(item.Name));//獲取到對應的字段

        MemberBinding memberBinding = Expression.Bind(item, property);//同上

        memberBindingList.Add(memberBinding);

    }

 MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TDestination)), memberBindingList.ToArray());//初始化創建新對象

    Expression<Func<TSource, TDestination>> lambda = Expression.Lambda<Func<TSource, TDestination>>(memberInitExpression, parameterExpression);

    return lambda.Compile()(source); //拼裝是一次性的

}

8. 表达式树缓存实现通用实体的互换

实现思路:把每次编译后的表达式树缓存起來,如果存在,直接拿現成的编译好的表达式树调用就好了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/// <summary>

/// 生成表達式目錄樹。字典緩存

/// </summary>

public class ExpressionMapper
{

   private static Dictionary<string, object> _dic = new Dictionary<string, object>();//緩存字典,緩存后的就是硬編碼所以性能高。



 /// <summary>

    /// 字典緩存表達式樹

    /// </summary>

    /// <typeparam name="TSource"></typeparam>

 /// <typeparam name="TDestination"></typeparam>

    /// <param name="source"></param>

    /// <returns></returns>

    public static TDestination Map<TSource, TDestination>(TSource source)

    {

 string key = $"funckey_{typeof(TSource).FullName}_{typeof(TDestination).FullName}";

 if (!_dic.ContainsKey(key)) //如果該表達式不存在,則走一遍編譯過程

     {

            ParameterExpression parameterExpression = Expression.Parameter(typeof(TSource), "p");

            List<MemberBinding> memberBindingList = new List<MemberBinding>();//表示綁定的類派生自的基類,這些綁定用于對新創建對象的成員進行初始化(vs的注解。太生澀了,我這樣的小白解釋不了,大家將就著看)

            foreach (var item in typeof(TDestination).GetProperties()) //遍歷目標類型的所有屬性
           {

                MemberExpression property = Expression.Property(parameterExpression, typeof(TSource).GetProperty(item.Name));//獲取到對應的屬性

                MemberBinding memberBinding = Expression.Bind(item, property);//初始化這個屬性

                memberBindingList.Add(memberBinding);

            }
            foreach (var item in typeof(TDestination).GetFields())//遍歷目標類型的所有字段

            {

                MemberExpression property = Expression.Field(parameterExpression, typeof(TSource).GetField(item.Name));//獲取到對應的字段

                MemberBinding memberBinding = Expression.Bind(item, property);//同上
                memberBindingList.Add(memberBinding);

            }

            MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TDestination)), memberBindingList.ToArray());//初始化創建新對象

            Expression<Func<TSource, TDestination>> lambda = Expression.Lambda<Func<TSource, TDestination>>(memberInitExpression, parameterExpression);

            _dic[key] = lambda.Compile(); //拼裝是一次性的

        }

        return ((Func<TSource, TDestination>)_dic[key]).Invoke(source);

    }

}

9. 表达式树泛型缓存实现通用实体的相互转换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/// <summary>

/// 生成表達式目錄樹  泛型緩存

/// </summary>

public class ExpressionGenericMapper

{

    private static object func;

    public static TDestination Map<TSource, TDestination>(TSource source)
    {

       if (func is null)//如果表達式不存在,則走一遍編譯過程

        {

            ParameterExpression parameterExpression = Expression.Parameter(typeof(TSource), "p");

            var memberBindingList = new List<MemberBinding>();//表示綁定的類派生自的基類,這些綁定用于對新創建對象的成員進行初始化(vs的注解。太生澀了,我這樣的小白解釋不了,大家將就著看)

         foreach (var item in typeof(TDestination).GetProperties()) //遍歷目標類型的所有屬性

            {

                MemberExpression property = Expression.Property(parameterExpression, typeof(TSource).GetProperty(item.Name));//獲取到對應的屬性

                MemberBinding memberBinding = Expression.Bind(item, property);//初始化這個屬性

                memberBindingList.Add(memberBinding);

            }

            foreach (var item in typeof(TDestination).GetFields())

            {

                MemberExpression property = Expression.Field(parameterExpression, typeof(TSource).GetField(item.Name));//獲取到對應的字段

                MemberBinding memberBinding = Expression.Bind(item, property);//同上

                memberBindingList.Add(memberBinding);

            }

            MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TDestination)), memberBindingList.ToArray());//初始化創建新對象

           Expression<Func<TSource, TDestination>> lambda = Expression.Lambda<Func<TSource, TDestination>>(memberInitExpression, parameterExpression);

          func = lambda.Compile();

      }

        return ((Func<TSource, TDestination>)func)(source); //拼裝是一次性的

    }
}
使用 Hugo 构建
主题 StackJimmy 设计