.net C#类型之间相互转换

 

遇到问题描述

     在开发过程中经常遇到两个Model长得一模一样,但就是订单的类型不一样。常用到的框架结构是MVC中:业务逻辑层的Model与View层的Model的装换。每层定义属于自己Model,实现层与层之间的解耦。最简单小白的方法就是在每个要赋值的地方 new 一个 object, 之后实现一个一个赋值。

 

尝试写公用的方法

  A.通过反射获得原object中的内容,之后创建一个泛型的目标object对象,之后进行一一复制; 自己实现的实例如下:

                      最简单的只能实现一层转换 不支持list 结合的转换

/// <summary>
///OTO object到object 的转换
/// </summary>
/// <typeparam name="T1">目标类型 </typeparam>
/// <param name="sourceObject">要装换的object</param>
/// <param name="excludedProperties">装换的object中不需要装换的属性名称</param>
/// <returns></returns>

public static T1 MapProperties<T1>(object sourceObject, string[] excludeProperties = null) where T1 : class
{
var targetType = typeof(T1);
var targetObject = Activator.CreateInstance(targetType);
foreach (var sourceProperty in sourceObject.GetType().GetProperties())
{
if (excludeProperties != null && excludeProperties.Contains(sourceProperty.Name))
{
continue;
}

var targetObjectProperty = targetObject.GetType().GetProperty(sourceProperty.Name);
if (targetObjectProperty != null && sourceProperty.PropertyType == targetObjectProperty.PropertyType)
{
var sourceValue = sourceProperty.GetValue(sourceObject);
targetObjectProperty.SetValue(targetObject, sourceValue);
}
}
return (T1)targetObject;
}

 

                        能实现一层与简单2层的(2层中引用对象的类型一致),不支持list集合的方式

               /// <summary>

/// 转换两个不同类型但是成员相同的对象,包含私有字段的赋值
/// </summary>
/// <typeparam name="T">目标对象</typeparam>
/// <param name="source">待转换对象</param>
/// <returns></returns>
public static T CopySameFieldsObject<T>(Object source) where T: class
{
Type srcT = source.GetType();
Type destT = typeof(T);

// 构造一个要转换对象实例
Object instance = destT.InvokeMember("", BindingFlags.CreateInstance, null, null, null);

// 这里指定搜索所有公开和非公开的字段
FieldInfo[] srcFields = srcT.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

// 将源头对象的每个字段的值分别赋值到转换对象里,因为假定字段都一样,这里就不做容错处理了
foreach (FieldInfo field in srcFields)
{
 destT.GetField(field.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).
 SetValue(instance, field.GetValue(source));
}

return (T)instance;
}

              

 1     public class PagerModel 
 2     {
 3         public PagerModel()
 4         {
 5             TastPageModel = new TastPageModel();
 6             TastPageModels = new List<TastPageModel>();
 7         }
 8 
 9         public int CurrentPage { get; set;}
10         public int PageSize { get; set;}
11         public int Total { get; set;}
12         public int TotalPage 
13         {
14             get
15             {
16                 return (this.Total + this.PageSize - 1) / this.PageSize;
17             }
18         }
19         //简单序列化对象
20         public override string ToString()
21         {
22             return JsonConvert.SerializeObject(this);
23         }
24         public TastPageModel TastPageModel;
25 
26         public List<TastPageModel> TastPageModels;
27 
28     }
29 
30     public class TastPageModel
31     {
32         public  string TastString { get; set;}
33 
34         public Object ObjTry { get; set;}  
35     }
36 
37     public class TastPageModel2
38     {
39         public string TastString { get; set; }
40 
41         public Object ObjTry { get; set; }
42     }
43     public class PagerModel2
44     {
45         public PagerModel2() {
46             TastPageModel = new TastPageModel();
47             TastPageModels = new List<TastPageModel2>();
48         }
49 
50         public TastPageModel TastPageModel;
51         public List<TastPageModel2> TastPageModels;
52         public int CurrentPage { get; set; }
53         public int PageSize { get; set; }
54         public int Total { get; set; }
55         public int TotalPage
56         {
57             get
58             {
59                 return (this.Total + this.PageSize - 1) / this.PageSize;
60             }
61         }
62         //简单序列化对象
63         public override string ToString()
64         {
65             return JsonConvert.SerializeObject(this);
66         }
67     }
68  
69 
70 ----运行代码
71 
72  public static void MapTest()
73         {
74             var model = new PagerModel()
75             {
76                 Total=100,
77                 PageSize = 20
78             };
79             model.TastPageModel.TastString = "aaaaa";
80 
81 
82              model.TastPageModels.Add(new TastPageModel() {
83                             TastString = "bbbb",
84                             ObjTry = new  {
85                                oa="ccccc",
86                             }
87                         });
88 
89             var model3 = ModelMap.CopySameFieldsObject<PagerModel2>(model);
90             //var model2 = ModelMap.MapProperties<PagerModel2>(model);
91         }
view code

试验结果就是:

(1)转换对象层级是一级的是没有问题;

(2)二级的类是一致的也能装换(可以把PagerModel2 中成员 public List<TastPageModel2> TastPageModels;  改为 public List<TastPageModel> TastPageModels);

(3)二级中类成员是一致的,但是属于不同的类型就不行了,上边实例中充分说明了这一点。多级的就更不用说了。

 结论:

 这种方法是可以实现我们的目的,但是可能要处理,考虑的点比较多,容易形成漏洞。就是说轮子是这样造的,但是我们不用在重新去研究具体怎么造的。

B:最简单暴力的处理方式,管你里面有什么东西,直接Json序列化,再反序列化,使用这种方式的人,大部分是不愿意引用第三方插件。

   其中需要安装 System.Security.Permissions包

 /// <summary>
/// 将object对象转换为实体对象序列化与反序列化的方式
/// </summary>
/// <typeparam name="T">实体对象类名</typeparam>
/// <param name="asObject">object对象</param>
/// <returns></returns>
public static T ConvertObject<T>(object sourceObject) where T : class
{
if (sourceObject == null)
{
return null;
}
//将object对象转换为json字符
var json = Newtonsoft.Json.JsonConvert.SerializeObject(sourceObject);
//将json字符转换为实体对象
var targetObject = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(json);
return targetObject;
}

          试验结果: 完美解决遇到的大部分问题,为什么是大部分呢? 执行的效率怎么样?有没有字节的限制? 需要我们去验证。

 

 C:找专业的第三方插件,现在常用到的就是AutoMapper,可以在Nuget包中添加,本次试验用的版本是(8.1.1) 48M大小。

     我们采用这种拿来主义的话,就探讨一下他的执行效率,可以反编译去查看一下里面的实现方式。自己可以学习一下。其中的反编译工具用的是ILSpy 。  AutoMapper 中的内容比较多,你编程中用到的所有装换问题都能实现

AutoMapper Github上源代码: AutoMapper  https://github.com/AutoMapper/AutoMapper

 

ILSpy Github上源代码(以及下载地址):https://github.com/icsharpcode/ILSpy#ilspy-------  (可Download: latest release  下载最新版本的zip包,直接exe打开运行)

AutoMapper 官网使用手册: http://docs.automapper.org/en/latest/Dependency-injection.html   

AutoMapper 博客大神们分享8分钟学会使用automapper:  https://www.cnblogs.com/ZaraNet/p/10000311.html 

                                                              博客园中系列文档 :https://www.cnblogs.com/xishuai/p/3700052.html

                                                              CSDN上系列文档:  https://blog.csdn.net/WuLex/article/details/78646260

用户比较详细的测试用例在github中 : https://github.com/AutoMapper/AutoMapper/blob/master/src/IntegrationTests/ChildClassTests.cs

 

 

在这里我们自己写的实例在这里给了一个比较常用的类型转换的实例  Expression-Translation ,这两个实例是立马都能上手用的装换,其他比较复杂,就需要自己去找文档了,

//4.AutoMapper 中使用的情况
//现在一般是使用依赖注入的方式
Mapper.Initialize(cfg => {
cfg.CreateMap<PagerModel, PagerModel2>();
cfg.CreateMap<TastPageModel, TastPageModel2>();
});
var model6 = AutoMapper.Mapper.Map<PagerModel2>(model);

//5.AutoMapper 中List 的转换
var model7 = AutoMapper.Mapper.Map<List<PagerModel2>>(modellist);

 
View Code

 B,C两种执行效率的比对:   

 public static void MapTest()
        {
            var model = new PagerModel()
            {
                Total=100,
                PageSize = 20
            };
            model.TastPageModel.TastString = "aaaaa";


             model.TastPageModels.Add(new TastPageModel() {
                            TastString = "bbbb",
                            ObjTry = new  {
                               oa="ccccc",
                            }
                        });
            //1.自己写的装换的方法 只能装换类型完全一样的,不一样的会出错
            //var model3 = ModelMap.CopySameFieldsObject<PagerModel2>(model);

            //2.序列化与反序列化的试验
            //var model4 = ModelMap.ConvertObject<PagerModel2>(model);

            //3.探讨序列化中是否受字节的限制,以及性能上的优化状况
            var modellist = new List<PagerModel>();

            for (int i = 0; i < 1000000; i++)
            {
                var modelNew = new PagerModel()
                {
                    Total = 100,
                    PageSize = 20
                };
                modelNew.TastPageModel.TastString = "aaaaa";


                modelNew.TastPageModels.Add(new TastPageModel()
                {
                    TastString = "bbbb",
                    ObjTry = new
                    {
                        oa = "ccccc",
                    }
                });
                modellist.Add(modelNew);
            }
            var stopWatch = new Stopwatch();
            stopWatch.Start();
            var model5 = ModelMap.ConvertObject<List<PagerModel2>>(modellist);
            stopWatch.Stop();
            Console.WriteLine($"序列化与反序列化执行时间:{stopWatch.ElapsedMilliseconds}" );
            //4.AutoMapper 中使用的情况
            //现在一般是使用依赖注入的方式
                Mapper.Initialize(cfg => {
                    cfg.CreateMap<PagerModel, PagerModel2>();
                    cfg.CreateMap<TastPageModel, TastPageModel2>();
                });
                var model6 = AutoMapper.Mapper.Map<PagerModel2>(model);
            //5.AutoMapper 中List 的转换
             //执行时间的统计
            stopWatch.Reset();
            stopWatch.Start();
            var model7 = AutoMapper.Mapper.Map<List<PagerModel2>>(modellist);
            stopWatch.Stop();
            Console.WriteLine($"AutoMapper中的转换时间:{stopWatch.ElapsedMilliseconds}");
        }
View Code

执行结果:

   由此可见序列化与分序列化转换的速度还是太慢了.

 

转载于:https://www.cnblogs.com/q994321263/p/10974750.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值