In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the knowledge of "how to use expression tree to dynamically update the attribute value of a class". In the operation of actual cases, many people will encounter this dilemma. Next, let the editor lead you to learn how to deal with these situations! I hope you can read it carefully and be able to achieve something!
The lambda expression tree of C # is a good thing, which is not from other linguistics. If you are familiar with the lambda expression, you can realize the personalized operations of various scenarios, such as dynamic splicing query conditions, sorting methods, etc., as well as high-performance operations that replace reflection, such as IQueryable and IEnumerable, each expansion method is all λ expression tree.
This article shares the knowledge that C # uses expression tree (LambdaExpression) to dynamically update the attribute values of classes. In some businesses, you will encounter situations where you need to synchronize the attribute values of two classes, and some fields need to be filtered out. If you assign values manually, you need to write a lot of repetitive code:
Public class Teacher {public Guid Id {get; set;} public string Name {get; set;} public string Age {get; set;}} public class Student {public Guid Id {get; set;} public string Name {get; set;} public string Age {get; set }} / for example, you need to assign some attribute values of teacher to student, while id does not need to assign / public static void SetProperty (Student student, Teacher teacher) {if (student.Name! = teacher.Name) {student.Name = teacher.Name } if (student.Age! = teacher.Age) {student.Age = teacher.Age;}}
For performance considerations using reflection, try to write an extension method to build a method using the lambda expression tree
Public static class ObjectExtensions {/ cached expression / public static class MapperAccessor {private static Action func {get; set } public static TSource Set (TSource source, TTarget target, params string [] properties) {if (func = = null) {var sourceType = typeof (TSource); var targetType = typeof (TTarget); BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public If (properties.Length = = 0) {/ / get all properties if (sourceType = = targetType) {/ / get all attributes if they are of the same type Properties = sourceType.GetProperties (bindingFlags) .Select (x = > x.Name) .ToArray () } else {/ / if no specified attribute is passed, the attribute with the same name List propertyInfos = new List () is obtained by default. Foreach (var property in sourceType.GetProperties (bindingFlags)) {/ / different types specify attributes of the same name and the same type var targetProperty = targetType.GetProperty (property.Name, bindingFlags) If (targetProperty! = null & & targetProperty.PropertyType = = property.PropertyType) {propertyInfos.Add (property) }} properties = propertyInfos.Select (x = > x.Name) .ToArray () }} / / define three parameters of lambda: var s = Expression.Parameter (typeof (TSource), "s"); var t = Expression.Parameter (typeof (TTarget), "t"); var ps = Expression.Parameter (typeof (string []), "ps") / / get the generic extension method Contains var methodInfo = typeof (Enumerable). GetMethods (). FirstOrDefault (e = > e.Name = = "Contains" & & e.GetParameters (). Length = = 2) If (methodInfo = = null) {/ / properties.Contains () throw new NullReferenceException (nameof (methodInfo));} MethodInfo genericMethod = methodInfo.MakeGenericMethod (typeof (String)); / / create generic method List bs = new List () Foreach (string field in properties) {/ / get the attributes in the two types var sourceField = Expression.Property (s, field); var targetField = Expression.Property (t, field) / / create a conditional expression var notEqual = Expression.NotEqual (sourceField, targetField); / / sourceFieldqualified targetField var method = Expression.Call (null, genericMethod, ps, Expression.Constant (field)); / / ps.Contains (f) / / build the assignment statement var ifTrue = Expression.Assign (sourceField, targetField); / / the stitching expression sourceFieldvalues targets targets Fieldvalues expressions ps.Constructions (f) var condition = Expression.And (notEqual, Expression.IsTrue (method)) / / determine whether it is the same. If it is different, assign var expression = Expression.IfThen (condition, ifTrue); bs.Add (Expression.Block (expression));} var lambda = Expression.Lambda (Expression.Block (bs), s, t, ps) Func = lambda.Compile ();} func.Invoke (source, target, properties); return source }} / Update the attribute value of the source class with the same name through the target class / the data type to be updated / the target data type / the source data / target data / the attribute name to be changed / / return source data Updated public static TSource SetProperties (this TSource source, TTarget target, params string [] properties) {return MapperAccessor.Set (source, target, properties) }}
Write test methods
/ for example, some attribute values of teacher need to be assigned to student, while id does not need to be assigned / public static void SetProperty (Student student, Teacher teacher) {if (student.Name! = teacher.Name) {student.Name = teacher.Name } if (student.Age! = teacher.Age) {student.Age = teacher.Age;}} public static void SetProperty2 (Student student, Teacher teacher, params string [] properties) {var sourceType = student.GetType (); var targetType = teacher.GetType () Foreach (var property in properties) {var aP = sourceType.GetProperty (property); var bP = targetType.GetProperty (property); var apValue = aP.GetValue (student); var bpValue = bP.GetValue (teacher) If (apValue! = bpValue) {aP.SetValue (student, bpValue);} static (List, List) CreateData (int length) {var rd = new Random (); (List, List) ret; ret.Item1 = new List () Ret.Item2 = new List (); for (int I = 0; I
< length; i++) { Student student = new Student() { Id = Guid.NewGuid(), Name = Guid.NewGuid().ToString("N"), Age = rd.Next(1, 100) }; ret.Item1.Add(student); Teacher teacher = new Teacher() { Id = Guid.NewGuid(), Name = Guid.NewGuid().ToString("N"), Age = rd.Next(1, 100) }; ret.Item2.Add(teacher); } return ret; } static void Main(string[] args) { var length = 1000000; var data = CreateData(length); Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < length; i++) { SetProperty(data.Item1[i], data.Item2[i]); } sw.Stop(); Console.WriteLine($"手写方法耗时:{sw.ElapsedMilliseconds}ms"); data.Item1.Clear(); data.Item2.Clear(); var data2 = CreateData(length); sw.Restart(); for (int i = 0; i < length; i++) { data2.Item1[i].SetProperties(data2.Item2[i], nameof(Student.Age), nameof(Student.Name)); } data2.Item1.Clear(); data2.Item2.Clear(); sw.Stop(); Console.WriteLine($"lambda耗时:{sw.ElapsedMilliseconds}ms"); var data3 = CreateData(length); sw.Restart(); for (int i = 0; i < length; i++) { SetProperty2(data3.Item1[i], data3.Item2[i], nameof(Student.Age), nameof(Student.Name)); } sw.Stop(); Console.WriteLine($"反射耗时:{sw.ElapsedMilliseconds}ms"); data3.Item1.Clear(); data3.Item2.Clear(); Console.ReadKey(); }You can see the gap between the performance and the handwriting method, if the requirement is higher or the handwriting method, it is very painful to write if there are many fields. But this is enough for daily use, and it is an extension method, which is very versatile.
This is the end of the content of "how to use the expression tree to dynamically update the attribute values of a class". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.