C # quickly and efficiently copy objects another way expression tree

Source: Internet
Author: User
Tags repetition

1. Demand

In the code you will often encounter the need to copy the object again, or the property name of the same value copied again.

Like what:

     Public classStudent { Public intId {Get;Set; }  Public stringName {Get;Set; }  Public intAge {Get;Set; } }     Public classStudentsecond { Public intId {Get;Set; }  Public stringName {Get;Set; }  Public intAge {Get;Set; } }

Student s = new Student () {age = $, Id = 1, Name = "Emrys"};

We need to assign a new student.

Student ss = new Student {age = s.age, Id = s.id, Name = s.name};

or assign a value to a property of another class Studentsecond, the name and type of the two class property are the same.

Studentsecond ss = new Studentsecond {age = s.age, Id = s.id, Name = s.name};

2. Solutions

The most primitive approach, of course, is to manually hand-write all properties that need to be assigned. This is the highest efficiency. But the repetition rate of the code is too high, and the code looks not beautiful, more important is a waste of time, if a class has dozens of attributes , that one property assignment is not a waste of energy, such as the repetition of the work should be optimized.

2.1. Reflection

Reflection should be a method used by many people, that is, encapsulating a class, reflecting the Get property and setting the value of the property.

        Private StaticTOut Transreflection<tin, tout>(Tin Tin) {TOut TOut= activator.createinstance<tout>(); foreach(varItemoutinchTout.gettype (). GetProperties ()) {varItemIn = Tin.gettype (). GetProperties (). Where (i = I.name = =itemout.name).                FirstOrDefault (); if(ItemIn! =NULL) {Itemout.setvalue (TOut, Itemin.getvalue (tIn)); }            }            returnTOut; }

Call:studentsecond ss= transreflection<student, studentsecond> (s);

Call 1 million times time:2464 milliseconds

2.2. Serialization

There are many ways to serialize, with binary, XML, JSON, and so on, and today we're testing with newtonsoft json.

Call:studentsecond ss= jsonconvert.deserializeobject<studentsecond> ( Jsonconvert.serializeobject (s));

call 1 million times time consuming: 2984 Ms

From this we can see that the efficiency of serialization and reflection is not very different.

3. Expression Tree 3.1, Introduction

About the expression tree do not understand can Baidu.

This means that copying an object can also be used in the expression tree.

        New Studentsecond {age = x.age, Id = x.id, Name = x.name};         var f = ss.compile ();         = f (s);

In this way we can achieve the same effect.

Some people say that this kind of writing and the original copy is no different, the code is more, this is only the first step.

3.2. Analysis Code

We use Ilspy to decompile This expression code as follows:

parameterexpression parameterexpression; Expression<func<student, studentsecond>> ss = Expression.lambda<func<student, StudentSecond>> ( Expression.memberinit (Expression.new (typeof(Studentsecond)),Newmemberbinding[] {expression.bind (Methodof (Studentsecond.set_age (int) , Expression.property (ParameterExpression, Methodof (Student.get_age ())), Expression.bind (Methodof ( STUDENTSECOND.SET_ID (int) , Expression.property (ParameterExpression, Methodof (student.get_id ())), Expression.bind (Methodof ( Studentsecond.set_name (string)) , Expression.property (ParameterExpression, Methodof (Student.get_name () ))),Newparameterexpression[] {parameterexpression}); Func<student, studentsecond> f =Ss.compile (); Studentsecond Studentsecond= f (s);

So that means we just loop all the properties with reflection and then expression.bind all the properties . Finally call compile () (s) to get the correct studentsecond.

See this some people asked again, if the reflection is not inefficient, and direct use of reflection or serialization with no difference?

Of course this can be solved, is that our expression tree can be cached . It is only necessary for the first time to use the reflection, and later use will not need to reflect.

3.3. Copy object Generic Code

For versatility, the student and Studentsecond are replaced by generics respectively.

        Private Staticdictionary<string,Object> _dic =Newdictionary<string,Object>(); Private StaticTOut Transexp<tin, tout>(Tin Tin) {stringKey =string. Format ("Trans_exp_{0}_{1}",typeof(TIn). FullName,typeof(TOut).            FullName); if(!_dic.containskey (Key)) {parameterexpression parameterexpression= Expression.parameter (typeof(TIn),"P"); List<MemberBinding> memberbindinglist =NewList<memberbinding>(); foreach(varIteminch typeof(TOut). GetProperties ()) {Memberexpression property= Expression.property (ParameterExpression,typeof(TIn). GetProperty (item.                    Name)); Memberbinding memberbinding=Expression.bind (item, property);                Memberbindinglist.add (memberbinding); } memberinitexpression memberinitexpression= Expression.memberinit (Expression.new (typeof(TOut)), Memberbindinglist.toarray ()); Expression<func<tin, tout>> lambda = expression.lambda<func<tin, tout>> (Memberinitexpression,Newparameterexpression[] {parameterexpression}); Func<tin, tout> func =Lambda.compile (); _dic[key]=func; }            return(Func<tin, tout>) _dic[key]) (tIn); }

Call:studentsecond ss= transexp<student, studentsecond> (s);

call 1 million times time:564 milliseconds

4. Summary

From the above test and analysis can be easily concluded that the expression tree is a way to achieve both efficiency and writing methods , in short, than the traditional serialization and reflection more excellent.

Finally, I hope you have some help, this article is original, welcome to make bricks and recommend .

C # quickly and efficiently copy objects another way expression tree

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.