C # Another method of Expression Tree for copying objects quickly and efficiently,

Source: Internet
Author: User

C # Another method of Expression Tree for copying objects quickly and efficiently,
1. Requirements

In the code, you often need to copy the object or copy the values with the same attribute name.

For example:

    public class Student    {        public int Id { get; set; }        public string Name { get; set; }         public int Age { get; set; }     }    public class StudentSecond    {        public int Id { get; set; }        public string Name { get; set; }        public int Age { get; set; }     }

Student s = new Student () {Age = 20, Id = 1, Name = "Emrys "};

We need to assign a value to the new Student.

Student ss = new Student {Age = s. Age, Id = s. Id, Name = s. Name };

Or assign a value to the attributes of another class StudentSecond. The names and types of the two class attributes are the same.

StudentSecond ss = new StudentSecond {Age = s. Age, Id = s. Id, Name = s. Name };

 

2. Solution

Of course, the most primitive method is to manually write all the attributes to be assigned values. This is the most efficient. However, the Code repetition rate is too high, and the Code does not look beautiful. More importantly, it is a waste of time. If a class has dozens of attributesOne by oneAttribute assignment is not a waste of energy. repetitive work like this should be optimized.

2.1 reflection

Reflection is a method that many people have used. It encapsulates a class, and reflection gets attributes and sets attribute values.

        private static TOut TransReflection<TIn, TOut>(TIn tIn)        {            TOut tOut = Activator.CreateInstance<TOut>();            foreach (var itemOut in tOut.GetType().GetProperties())            {                var itemIn = tIn.GetType().GetProperties().Where(i => i.Name == itemOut.Name).FirstOrDefault();                if (itemIn != null)                {                    itemOut.SetValue(tOut, itemIn.GetValue(tIn));                }            }            return tOut;        }

Call:StudentSecond ss = TransReflection <Student, StudentSecond> (s );

Call time: 1 million milliseconds

 

2.2 serialization

There are many serialization methods, such as binary, xml, and json. Today we will use Newtonsoft json for testing.

Call:StudentSecondSs= JsonConvert. DeserializeObject <StudentSecond> (JsonConvert. SerializeObject (s ));

Call time:2984 Ms

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

 

3. Expression Tree 3.1, Introduction

Baidu is not familiar with the expression tree.

That is to say, you can use the expression tree to copy objects.

        Expression<Func<Student, StudentSecond>> ss = (x) => new StudentSecond { Age = x.Age, Id = x.Id, Name = x.Name };        var f = ss.Compile();        StudentSecond studentSecond = f(s);

In this way, we can achieve the same effect.

Some people say that this writing method is no different from the original copy method, but the code is getting more. This is only the first step.

 

3.2 analyze code

We use ILSpy to decompile the code of this expression as follows:

   ParameterExpression parameterExpression;    Expression<Func<Student, StudentSecond>> ss = Expression.Lambda<Func<Student, StudentSecond>>(Expression.MemberInit(Expression.New(typeof(StudentSecond)), new MemberBinding[]    {        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())))    }), new ParameterExpression[]    {        parameterExpression    });    Func<Student, StudentSecond> f = ss.Compile();    StudentSecond studentSecond = f(s);

So we only need to useReflection loops all attributes and then Expression. Bind all attributes. Finally, call Compile () (s) to obtain the correct StudentSecond.

If reflection is used, isn't it very efficient? Is there any difference between reflection and serialization?

Of course, what this can solve is that our expression tree canCache. Only reflection is required for the first time, and reflection is not required for later use.

 

3.3 copy Common Object Code

For the sake of universality, Student and StudentSecond are replaced with generics respectively.

        private static Dictionary<string, object> _Dic = new Dictionary<string, object>();        private static TOut TransExp<TIn, TOut>(TIn tIn)        {            string key = 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 = new List<MemberBinding>();                foreach (var item in 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, new ParameterExpression[] { 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 time: 1 millionMillisecond

 

4. Summary

From the above tests and analysis, we can easily conclude that the expression tree can be used to achieveEfficiencyAndWriting MethodBoth methodsOne,In short, it is better than traditional serialization and reflection.

I hope it will be helpful to you. This article is original and you are welcome to make a brick andRecommendation.

 

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.