最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#使用表達(dá)式樹(shù)(LambdaExpression)動(dòng)態(tài)更新類的屬性值(示例代碼)

 更新時(shí)間:2022年01月11日 11:20:37   作者:tchivs  
這篇文章主要介紹了C#使用表達(dá)式樹(shù)(LambdaExpression)動(dòng)態(tài)更新類的屬性值,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

有看過(guò)我之前發(fā)表過(guò)的C#相關(guān)文章分享和閱讀過(guò)我代碼的朋友們可能會(huì)在我的代碼里面經(jīng)??吹礁鞣N各樣的λ表達(dá)式動(dòng)態(tài)拼接,C#的λ表達(dá)式樹(shù)是一個(gè)好東西,也是別的語(yǔ)言學(xué)不來(lái)的,熟悉掌握λ表達(dá)式就能夠?qū)崿F(xiàn)各種場(chǎng)景的個(gè)性化操作,如動(dòng)態(tài)拼接查詢條件、排序方式等,也能夠?qū)崿F(xiàn)替代反射的高性能操作,比如我們常用到的IQueryable和IEnumerable,每個(gè)擴(kuò)展方法就全是λ表達(dá)式樹(shù)。

本文給大家分享C#使用表達(dá)式樹(shù)(LambdaExpression)動(dòng)態(tài)更新類的屬性值的相關(guān)知識(shí),在某些業(yè)務(wù)中會(huì)遇到需要同步兩個(gè)類的屬性值的情況,而且有些字段是要過(guò)濾掉的。如果手動(dòng)賦值則需要寫很多重復(fù)的代碼:

 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; }
        }
   /// <summary>
        /// 比如需要把teacher的某些屬性值賦給student,而id不需要賦值
        /// </summary>
        /// <param name="student"></param>
        /// <param name="teacher"></param>
        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;
            }
        }

使用反射的話性能考慮,嘗試寫一個(gè)擴(kuò)展方法使用lambda表達(dá)式樹(shù)去構(gòu)建一個(gè)方法

public static class ObjectExtensions
    {
        /// <summary>
        /// 緩存表達(dá)式
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TTarget"></typeparam>
        public static class MapperAccessor<TSource, TTarget>
        {
            private static Action<TSource, TTarget, string[]> 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)
                        {
                            //如果是相同類型則獲取所有屬性
                            properties = sourceType.GetProperties(bindingFlags).Select(x => x.Name)
                                .ToArray();
                        }
                        else
                        {
                            //如果沒(méi)有傳指定的屬性則默認(rèn)獲取同名屬性
                            List<PropertyInfo> propertyInfos = new List<PropertyInfo>();
                            foreach (var property in sourceType.GetProperties(bindingFlags))
                            {//不同類型指定同名且類型相同的屬性
                                var targetProperty = targetType.GetProperty(property.Name, bindingFlags);
                                if (targetProperty != null && targetProperty.PropertyType == property.PropertyType)
                                {
                                    propertyInfos.Add(property);
                                }
                            }
                            properties = propertyInfos.Select(x => x.Name).ToArray();
                        }
                    }
                    //定義lambda 3個(gè)參數(shù)
                    var s = Expression.Parameter(typeof(TSource), "s");
                    var t = Expression.Parameter(typeof(TTarget), "t");
                    var ps = Expression.Parameter(typeof(string[]), "ps");
                    //獲取泛型擴(kuò)展方法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));//創(chuàng)建泛型方法
                    List<BlockExpression> bs = new List<BlockExpression>();
                    foreach (string field in properties)
                    {
                        //獲取兩個(gè)類型里面的屬性
                        var sourceField = Expression.Property(s, field);
                        var targetField = Expression.Property(t, field);
                        //創(chuàng)建一個(gè)條件表達(dá)式
                        var notEqual = Expression.NotEqual(sourceField, targetField);//sourceField!=targetField
                        var method = Expression.Call(null, genericMethod, ps, Expression.Constant(field));//ps.Contains(f);
                        //構(gòu)建賦值語(yǔ)句
                        var ifTrue = Expression.Assign(sourceField, targetField);
                        //拼接表達(dá)式 sourceField!=targetField&&ps.Contains(f)
                        var condition = Expression.And(notEqual, Expression.IsTrue(method));
                        //判斷是否相同,如果不相同則賦值
                        var expression = Expression.IfThen(condition, ifTrue);
                        bs.Add(Expression.Block(expression));
                    }
                    var lambda = Expression.Lambda<Action<TSource, TTarget, string[]>>(Expression.Block(bs), s, t, ps);
                    func = lambda.Compile();
                }
                func.Invoke(source, target, properties);
                return source;
            }
        }
        /// <summary>
        /// 通過(guò)目標(biāo)類更新源類同名屬性值
        /// </summary>
        /// <typeparam name="TSource">待更新的數(shù)據(jù)類型</typeparam>
        /// <typeparam name="TTarget">目標(biāo)數(shù)據(jù)類型</typeparam>
        /// <param name="source">源數(shù)據(jù)</param>
        /// <param name="target">目標(biāo)數(shù)據(jù)</param>
        /// <param name="properties">要變更的屬性名稱</param>
        /// <returns>返回源數(shù)據(jù),更新后的</returns>
        public static TSource SetProperties<TSource, TTarget>(this TSource source, TTarget target, params string[] properties)
        {
            return MapperAccessor<TSource, TTarget>.Set(source, target, properties);
        }
    }

編寫測(cè)試方法

 /// <summary>
        /// 比如需要把teacher的某些屬性值賦給student,而id不需要賦值
        /// </summary>
        /// <param name="student"></param>
        /// <param name="teacher"></param>
        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<Student>, List<Teacher>) CreateData(int length)
        {
            var rd = new Random();
            (List<Student>, List<Teacher>) ret;
            ret.Item1 = new List<Student>();
            ret.Item2 = new List<Teacher>();
            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($"手寫方法耗時(shí):{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耗時(shí):{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($"反射耗時(shí):{sw.ElapsedMilliseconds}ms");
            data3.Item1.Clear();
            data3.Item2.Clear();
      
            Console.ReadKey();
        }

可以看到性能和手寫方法之間的差距,如果要求比較高還是手寫方法,如果字段多的話寫起來(lái)是很痛苦的事。但是日常用這個(gè)足夠了,而且是擴(kuò)展方法,通用性很強(qiáng)。

到此這篇關(guān)于C#使用表達(dá)式樹(shù)(LambdaExpression)動(dòng)態(tài)更新類的屬性值的文章就介紹到這了,更多相關(guān)C#表達(dá)式樹(shù)類的屬性值內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#中常用窗口特效的實(shí)現(xiàn)代碼

    C#中常用窗口特效的實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了C#中三個(gè)常用的窗口特效的實(shí)現(xiàn),分別是淡入淡出、變大變小、緩升緩降,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • 將excel數(shù)據(jù)轉(zhuǎn)換成dataset示例

    將excel數(shù)據(jù)轉(zhuǎn)換成dataset示例

    這篇文章主要介紹了不借助第三方插件的情況下將Excel中的數(shù)據(jù)轉(zhuǎn)換成DataSet的方法,需要的朋友可以參考下
    2014-02-02
  • LZW數(shù)據(jù)壓縮算法的原理分析

    LZW數(shù)據(jù)壓縮算法的原理分析

    我希望通過(guò)本文的介紹,能給那些目前不太了解lzw算法和該算法在gif圖像中應(yīng)用,但渴望了解它的人一些啟發(fā)和幫助。拋磚引玉而已,更希望兄弟們提出寶貴的意見(jiàn)。
    2016-06-06
  • C#實(shí)現(xiàn)文本文件讀寫方法匯總

    C#實(shí)現(xiàn)文本文件讀寫方法匯總

    本文給大家匯總介紹了C#實(shí)現(xiàn)文本文件讀寫的方法,十分的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。
    2015-06-06
  • 詳解C#如何實(shí)現(xiàn)分割視頻

    詳解C#如何實(shí)現(xiàn)分割視頻

    這篇文章主要為大家詳細(xì)介紹了C#如何實(shí)現(xiàn)將視頻文件分割成一幀幀圖片的方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-12-12
  • C#使用dynamic類型訪問(wèn)JObject對(duì)象

    C#使用dynamic類型訪問(wèn)JObject對(duì)象

    這篇文章主要為大家詳細(xì)介紹了C#使用dynamic類型訪問(wèn)JObject對(duì)象,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • c# xml轉(zhuǎn)word的實(shí)現(xiàn)示例

    c# xml轉(zhuǎn)word的實(shí)現(xiàn)示例

    這篇文章主要介紹了c# xml轉(zhuǎn)word的實(shí)現(xiàn)示例,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-04-04
  • C#簡(jiǎn)單實(shí)現(xiàn)在網(wǎng)頁(yè)上發(fā)郵件的案例

    C#簡(jiǎn)單實(shí)現(xiàn)在網(wǎng)頁(yè)上發(fā)郵件的案例

    本文分享一個(gè)C#利用SMTP發(fā)送郵件的案例,提供了前后臺(tái)代碼,方便大家學(xué)習(xí)。
    2016-03-03
  • C# 9 中新加入的關(guān)鍵詞 init,record,with

    C# 9 中新加入的關(guān)鍵詞 init,record,with

    這篇文章主要介紹了C# 9 中新加入的關(guān)鍵詞 init,record,with的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c# 9,感興趣的朋友可以了解下
    2020-08-08
  • 詳解C#如何加密解密RAR文件

    詳解C#如何加密解密RAR文件

    這篇文章主要為大家詳細(xì)介紹了C#如何實(shí)現(xiàn)加密解密RAR文件的功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-12-12

最新評(píng)論

宣汉县| 体育| 安龙县| 行唐县| 河西区| 铜陵市| 湖北省| 张掖市| 巫山县| 汝城县| 合川市| 康保县| 岑溪市| 杭锦后旗| 察哈| 石首市| 乌鲁木齐县| 台安县| 蛟河市| 河西区| 大庆市| 石嘴山市| 汕尾市| 和龙市| 平安县| 盐津县| 军事| 永清县| 临汾市| 龙南县| 仁怀市| 凌云县| 若尔盖县| 观塘区| 贡嘎县| 拜城县| 皋兰县| 乌拉特后旗| 石首市| 牡丹江市| 固阳县|