首页 > 作文

C#使用表达式树实现对象复制的示例代码

更新时间:2023-04-04 10:00:37 阅读: 评论:0

需求背景:对象复制性能优化;同时,在对象复制时,应跳过引用类型的null值复制,值类型支持值类型向可空类型的复制

using common;using syst撩妹回复em;class program{    static void main(string[] args)    {        testclassa classa = new testclassa() { propa = new testclass() { name = "cs1" }, propb = "c1", propc = 1 };        testclassa classb = new testclassa() { propa = new testclass() { name = "cs2" }, propb = "c2", propc = 2 };        fastcopy.copy(classa, classb, fal);        console.writeline(classb.propa?.name + ":" + classb.propb + ":" + classb.propc);        testclassa classc = new testclassa() { propa = new testclass() { name = "cs1" } };        testclassa classd = new testclassa() { propa = new testclass() { name = "cs2" }, propb = "c2", propc = 2 };        fastcopy.copy(classc, classd, fal);        console.writeline(classd.propa?.name + ":" + classd.propb + ":" + classd.propc);    }}public class testclassa{    public testclass propa { get; t; }    public string propb { get; t; }    public int? propc { get; t; }}public class testclass{    public string name { get; t; }}

输出:

百万次调用耗时:270-300ms

using system;using system.collections.concurrent;using system.collections.generic;using system.linq;using system.linq.expressions;using system.reflection;using static system.linq.expressions.expression;namespace common{    public static class fastcopy    {        static concurrentdictionary<string, object> copiers = new concurrentdictionary<string, object>();        /// <summary>        /// 复制两个对象同名属性值        /// </summary>        /// <typeparam name="s"></typeparam>        /// <typeparam name="t"></typeparam>        /// <param name="source">源对象</param>        /// <param name="target">目标对象</param>        /// <param name="copynull">源对象属性值为null时,是否将值复制给目标对象</param>        public static void copy<s, t>(s source, t target, bool copynull = true)        {            string name = string.format("{0}_{1}_{2}", typeof(s), typeof(t), copynull);            object targetcopier;            if (!copiers.trygetvalue(name, out targetcopier))            {                action<s, t> copier = createcopier<s, t>(copynull);                copiers.tryadd(name, copier);                targetcopier = copier;          我得到什么  }            action<s, t> action = (action<s, t>)targetcopier;            action(source, target);        }        /// <summary>        /// 为指定的两种类型编译生成属性复制委托        /// </summary>        /// <typeparam name="s"></typeparam>        /// <typeparam name="t"></typeparam>        /// <param name="copynull">源对象属性值为null时,是否将值复制给目标对象</param>        /// <returns></returns>        private static action<s, t> createcopier<s, t>(bool copynull)        {            parameterexpression source = parameter(typeof(s));            parameterexpression target = parameter(typeof(t));            var sourceprops = typeof(s).getproperties(bindingflags.instance | bindingflags.public).where(p => p.canread).tolist();            var targetprops = typeof(t).getproperties(bindingflags.instance | bindingflags.public).where(p => p.canwrite).tolist();            // 查找可进行赋值的属性            var copyprops = targetprops.where(tprop => sourceprops.where(sprop => sprop.name == tprop.name// 名称一致 且            && (            sprop.propertytype == tprop.propertytype// 属性类型一致 或            || sprop.propertytype.isassignablefrom(tprop.propertytype) // 源属性类型 为 目标属性类型 的 子类;eg:object target = string source;   或            || (tprop.propertytype.isvaluetype && sprop.propertytype.isvaluetype && // 属性为值类型且基础类型一致,但目标属性为可空类型 eg:int? num = int num;            ((tprop.propertytype.generictypearguments.length > 0 ? tprop.propertytype.generictypearguments[0] : tprop.propertytype) == sprop.propertytype))            )).count() > 0);            list<expression> expressionlist = new list<expression>();            foreach (var prop in copyprops)            {                if (prop.propertytype.isvaluetype)// 属性为值类型                {                    propertyinfo sprop = typeof(s).getproperty(prop.name);                    propertyinfo tprop = typeof(t).getproperty(prop.name);                    if (sprop.propertytype == tprop.propertytype)// 属性类型一致 eg:int num = int num;    或   int? num = int? num;                    {                        var assign = assign(property(target, prop.name), property(source, prop.name));                        expressionlist.add(assign);                    }                    el if (sprop.propertytype.generictypearguments.length <= 0 && tprop.propertytype.generictypearguments.length > 0)// 属性类型不一致且目标属性类型为可空类型 eg:int? num = int num;                    {                        var convert = convert(expression.property(source, prop.name), tprop.propertytype);                        var cvassign = assign(expression.property(target, prop.name), convert);                        expressionlist.add(cvassign);                    }                }                el// 属性为引用类型                {                    var assign = assign(property(target, prop.name), property(source, prop.name));// 编译生成属性赋值语句   target.{propeum是什么单位rtyname} = source.{propertyname};                    var sourcepropisnull = equal(constant(null, prop.propertytype), property(source, prop.name));// 判断源属性值是否为null;编译生成  source.{propertyname} == null                    var tnull = istrue(constant(copynull));// 判断是否复制null值 编译生成  copynull == true                    var tnulltest = ifthen(tnull, assign);                    var condition = ifthenel(sourcepropisnull, tnulltest, assign);                    /**                     * 编译生成                     * if(source.{propertyname} == null)                     * {                     *   if(tnull)                     *   {                     *     target.{propertyname} = source.{propertyname};                     *   }                     * }                     * el                     * {                     *   target.{propertyname} = source.{propertyname};                     * }                     */                    expressionlist.add(condition);                }            }            var block = block(expressionlist.toarray());            expression<action<s, t>> lambda = lambda<action<s, t>>(block, source, target);            return lambda.compile();        }    }}

如果完整复制,去掉逻辑判断,同时可通过泛型类,不在使用字典,性能还可以提升。

using system;using system.linq;using system.linq.expressions;using system.reflection;namespace common{    public static class fastcopy<s, t>    {        static action<s, t> action = createcopier();        /// <summary>        /// 复制两个对象同名属性值        /// </summary>        /// <typeparam name="s"></typeparam>        /// <typeparam name="t"></typeparam>        /// <param name="source">源对象</param>        /// <param name="target">目标对象</param>        创新活动/// <param name="copynull">源对象属性值为null时,是否将值复制给目标对象</param>        public static void copy(s source, t target, bool copynull = true)        {            action(source, target);        }        /// <summary>        /// 为指定的两种类型编译生成属性复制委托        /// </summary>        /// <typeparam name="s"></typeparam>        /// <typepar2016msiam name="t"></typeparam>        /// <param name="copynull">源对象属性值为null时,是否将值复制给目标对象</param>        /// <returns></returns>        private static action<s, t> createcopier()        {            parameterexpression source = expression.parameter(typeof(s));            parameterexpression target = expression.parameter(typeof(t));            var sourceprops = typeof(s).getproperties(bindingflags.instance | bindingflags.public).where(p => p.canread).tolist();            var targetprops = typeof(t).getproperties(bindingflags.instance | bindingflags.public).where(p => p.canwrite).tolist();            // 查找可进行赋值的属性            var copyprops = targetprops.where(tprop => sourceprops.where(sprop => sprop.name == tprop.name// 名称一致 且            && (            sprop.propertytype == tprop.propertytype// 属性类型一致            )).count() > 0);            var block = expression.block(from p in copyprops lect expression.assign(expression.property(target, p.name), expression.property(source, p.name)));            expression<action<s, t>> lambda = expression.lambda<action<s, t>>(block, source, target);            return lambda.compile();        }    }}

百万次耗时:100ms左右

到此这篇关于c#使用表达式树实现对象复制的示例代码的文章就介绍到这了,更多相关c#表达式树对象复制内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

本文发布于:2023-04-04 10:00:35,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/546ec7c2cca659748c6b53bdfd22ef03.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:C#使用表达式树实现对象复制的示例代码.doc

本文 PDF 下载地址:C#使用表达式树实现对象复制的示例代码.pdf

下一篇:返回列表
标签:属性   对象   类型   目标
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图