当前位置: 首页 > 编程语言 > C#

重构以消除Lambda表达式中的重复

时间:2023-04-10 14:41:50 C#

重构以消除Lambda表达式中的重复这两个方法表现出重复:publicstaticExpressionEditDtoSelector(){returnf=>newFooEditDto{PropertyA=f.PropertyA,PropertyB=f.PropertyB,PropertyC=f.PropertyC,PropertyD=f.PropertyD,PropertyE=f.PropertyE};}publicstaticExpressionListDtoSelector(){returnf=>newFooDto{PropertyA=f.PropertyA,PropertyB=f.PropertyB,PropertyC=f.PropertyC};我如何重构以删除此重复项?更新:糟糕,我忽略了一个重要的点。FooEditDto是FooDto的子类。如果FooEditDto是FooDto的FooDto并且您不需要MemberInitExpressions,请使用构造函数:classFooDto{publicFooDto(Bara,Barb,Barc){PropertyA=a;物业B=b;属性C=c;}publicBarPropertyA{get;set;}publicBarPropertyB{get;set;}publicBarPropertyC{get;set;}}classFooEditDto:FooDto{publicFooEditDto(Bara,Barb,Barc):base(a,b,c)publicBarPropertyD{get;set;}publicBarPropertyE{get;set;}}publicstaticExpression>EditDtoSelector(){returnf=>newFooEditDto(f.PropertyA,f.PropertyB,f.PropertyC){PropertyD=f.PropertyD,PropertyE=f.PropertyE};好吧,我有一个非常糟糕的方法来做到这一点。您可以编写一个使用反射(请加我!)的方法来计算特定类型的所有属性,并构建一个委托(使用Reflection.Emit)将属性从该类型复制到另一个。然后使用匿名类型确保您只需构建一次复制委托,因此速度很快。您的方法将如下所示:细微差别:我不确定它是否真的值得,但这是一个非常有趣的想法......我可能不得不实施它:)编辑:使用MemberInitExpression我们可以用表达式树做任何事情,这使得它比CodeDOM快得多,也更容易。今晚会试一试...编辑:完成,它实际上是非常简单的代码。这是类级别://////从Copy方法中指定的源///类型复制到其目标类型的通用类。///单独指定类型以利用泛型///方法参数的类型推断。///publicstaticclassPropertyCopywhereTTarget:class,new(){//////将源中的所有可读属性复制到TTarget的///新实例。///publicstaticTTargetCopyFrom(TSourcesource)其中TSource:class{returnPropertyCopier.Copy(source);}//////静态类有效地存储可以///进行复制的已编译委托。我们需要做一些工作来确保异常被///适当地传播,因为异常是在类型初始化时///生成的,但我们希望它作为ArgumentException抛出。///privatestaticclassPropertyCopierwhereTSource:class{privatestaticreadonlyFunccopier;私有静态只读异常初始化异常;国米nalstaticTTargetCopy(TSourcesource){if(initializationException!=null){throwinitializationException;}if(source==null){thrownewArgumentNullException("source");}返回复印机(来源);}staticPropertyCopier(){尝试{copier=BuildCopier();初始化异常=空;}catch(Exceptione){复印机=null;初始化异常=e;}}privatestaticFuncBuildCopier(){ParameterExpressionsourceParameter=Expression.Parameter(typeof(TSource),"source");varbindings=newList();foreach(PropertyInfosourcePropertyintypeof(TSource).GetProperties()){if(!sourceProperty.CanRead){继续;}PropertyInfotargetProperty=typeof(TTarget).GetProperty(sourceProperty.Name);if(targetProperty==null){thrownewArgumentException("Property"+sourceProperty.Name+"在"+typeof(TTarget).FullName中不存在且不可访问);}if(!targetProperty.CanWrite){thrownewArgumentException("Property"+sourceProperty.Name+"在"+typeof(TTarget).FullName)中不可写;}if(!targetProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType)){thrownewArgumentException("Property"+sourceProperty.Name+"在"+typeof(TTarget).FullName中有不兼容的类型);}bindings.Add(Expression.Bind(targetProperty,Expression.Property(sourceParameter,sourceProperty)));}表达式初始值设定项=Expression.MemberInit(Expression.New(typeof(TTarget)),bindings);返回Expression.Lambda>(initializer,sourceParameter).Compile();}}并调用:TargetTypetarget=PropertyCopy.CopyFrom(new{First="Foo",Second="Bar"});名称中存在重复,但C#不知道一个类中的PropertyA与另一个类中的PropertyA关联您必须显式建立连接。你这样做的方式很好。如果你有足够的这些,你可以考虑使用反射来编写一个可以为任何一对类执行此操作的方法。请注意您选择的任何方法对性能的影响。反射本身比较慢。但是,您也可以使用反射来发出IL,并且一旦发出,它就会像您编写的一样快地运行。您还可以生成表达式树并将它们转换为已编译的委托。这些技术有点复杂,因此您必须做出权衡。可以让调用者只返回自己的匿名类型对象,只包含自己需要的属性:以上是C#学习教程:RefactoringtoeliminateduplicationinLambdaexpressions分享所有内容,如果对大家有用需要了解更多关于C#学习教程,希望大家多多关注—publicstaticExpression>GetSelector(Expression>f){returnf;}/*...*/varexpr=GetSelector(f=>new{f.PropertyA,f.PropertyB,f.PropertyC});本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: