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

表达式-Func-到表达式-Action--Getter-到-Setter-分享

时间:2023-04-11 10:38:39 C#

表达式到表达式"Getter"到"Setter"假设在这个例子中我的TModel是Customer类型并将它分配到某个地方,如下所示:);设置器(我的客户,价值);所以简而言之,我想以某种方式构建和编译一个表达式,将我的getter表达式指定的客户名称设置为特定值。修订。这个类可能比你能找到的许多其他类更好:-)这是因为这个版本支持直接属性(p=>pB)(像其他:-)),嵌套属性(p=>pBCD),字段(“结束”和“中间”,因此在p=>pBCD中,B和D都可以是字段)和“内部”类型转换(因此p=>((BType)pB).CD和p=>(pB作为BType)。CD)。唯一不支持的是铸造“终端”元素(所以没有p=>(object)pB)。生成器中有两个“代码路径”:简单表达式(p=>pB)和“嵌套”表达式。.NET4.0具有代码变体(具有Expression.Assign表达式类型)。从我的一些基准测试中,最快的代表是:“简单”Delegate.CreateDelegate用于属性,Expression.Assign用于字段,“简单”FieldSetter用于字段(这个比Expression.Assign用于字段慢一点)。因此,在.NET4.0下,您应该删除任何标记为3.5的代码。部分代码不是我的。初始(简单)版本基于FluentNHibernate代码(但它只支持直接属性),其他部分基于如何在C#表达式树中设置字段值?和.NET3.5表达式树中的赋值。publicstaticclassFluentTools{publicstaticActionGetterToSetter(Expression>getter){ParameterExpression参数;表达式实例;MemberExpression属性或字段;GetMemberExpression(getter,outparameter,outinstance,outpropertyOrField);//非常简单的情况:p=>p.Property或p=>p.Fieldif(parameter==instance){if(propertyOrField.Member.MemberType==MemberTypes.Property){//这比表达式树更快!(在我的基准测试中是5倍)但仅适用于属性PropertyInfoproperty=propertyOrField.MemberasPropertyInfo;MethodInfosetter=property.GetSetMethod();varaction=(Action)Delegate.CreateDelegate(typeof(Action),setter);返回动作;}#region.NET3.5else//if(propertyOrField.Member.MemberType==MemberTypes.Field){//比4.0方法慢1.2倍,比3.5方法快5倍FieldInfofield=propertyOrField.MemberasFieldInfo;varaction=FieldSetter(字段);返回动作;}#endregion}标准杆ameterExpressionvalue=Expression.Parameter(typeof(TValue),"val");表达式expr=null;#region.NET3.5if(propertyOrField.Member.MemberType==MemberTypes.Property){PropertyInfoproperty=propertyOrField.MemberasPropertyInfo;MethodInfosetter=property.GetSetMethod();expr=Expression.Call(实例,setter,值);}else//if(propertyOrField.Member.MemberType==MemberTypes.Field){expr=FieldSetter(propertyOrField,value);}#endregion//#region.NET4.0////对于字段访问,它比3.5方法快5倍,比“简单”方法快1.2倍。对于属性访问几乎相同的速度(快1.1倍)。//expr=Expression.Assign(propertyOrField,value);//#endregionreturnExpression.Lambda>(expr,parameter,value).Compile();}privatestaticvoidGetMemberExpression(Expression>expression,outParameterExpressionparameter,outExpressioninstance,outMemberExpressionpropertyOrField){Expressioncurrent=expression.Body;尽管(当前.NodeType==ExpressionType.Convert||current.NodeType==ExpressionType.TypeAs){current=(currentasUnaryExpression).Operand;}if(current.NodeType!=ExpressionType.MemberAccess){thrownewArgumentException();}propertyOrField=currentasMemberExpression;当前=propertyOrField.Expression;实例=当前;while(current.NodeType!=ExpressionType.Parameter){if(current.NodeType==ExpressionType.Convert||current.NodeType==ExpressionType.TypeAs){current=(currentasUnaryExpression).Operand;}elseif(current.NodeType==ExpressionType.MemberAccess){current=(currentasMemberExpression).Expression;}else{抛出新的ArgumentException();}}parameter=currentasParameterExpression;}#region.NET3.5//基于https://stackoverflow.com/questions/321650/how-do-i-set-a-field-value-in-an-c-expression-tree/321686#321686private静态动作FieldSetter(FieldInfo字段){DynamicMethodm=newDynamicMethod("setter",typeof(void),newType[]{typeof(T),typeof(TValue)},typeof(FluentTools));ILGeneratorcg=m.GetILGenerator();//参数0。=arg1cg.Emit(OpCodes.Ldarg_0);cg.Emit(OpCodes.Ldarg_1);cg.Emit(OpCodes.Stfld,field);cg.Emit(OpCodes.Ret);返回(动作)m.CreateDelegate(类型(动作));}//基于https://stackoverflow.com/questions/208969/assignment-in-net-3-5-expression-trees/3972359#3972359privatestaticExpressionFieldSetter(Expressionleft,Expressionright){returnExpression.Call(null,typeof(FluentTools).GetMethod("AssignTo",BindingFlags.NonPublic|BindingFlags.Static).MakeGenericMethod(left.Type),左,右);}privatestaticvoidAssignTo(refTleft,Tright)//注意'ref',它在分配left=right时很重要;//值类型!}#endregion}staticExpression>MakeSetter(Expression>getter){varmemberExpr=(MemberExpression)getter.Body;var@this=Expression.Parameter(typeof(T),"$this");varvalue=Expression.Parameter(typeof(TProperty),"value");返回Expression.Lambda>(Expression.Assign(Expression.MakeMemberAccess(@this,memberExpr.Member),value),@this,value);我有这个辅助方法,它返回属性的属性信息:publicstaticPropertyInfoGetPropertyInfo(Expression>property)whereT:class{varmemberExpression=(property.BodyasMemberExpression);如果(memberExpression!=null&&memberExpression.MemberisPropertyInfo){returnmemberExpression.MemberasPropertyInfo;}thrownewInvalidOperationException("GetPropertyInfo的无效使用");}用法:GetPropertyInfo((MyClassc)=>c.PropertyName);然后您可以使用PropertyInfo来设置类的属性值您需要修改代码以满足您的需要,但希望它有所帮助。我就是这样做的varexpParamV=表达式。参数(类型(对象),“v”);varexpParamVc=Expression.Convert(expParamV,pi.PropertyType);varmma=Expression.Call(expParamP,pi.GetSetMethod(),expParamVc);varexp=Expression.Lambda>(mma,expParamP,expParamV);返回exp.Compile();由于正确的答案对我不起作用(在表达式中设置)但将我推向了正确的方向,我需要对此进行大量调查,我想我想出了一种方法来为任何成员表达式生成setter。对于属性和字段,它的行为与标记的答案相同(我相信更透明)。它还对列表和字典有额外的支持——见注释。以上就是C#学习教程的全部内容:表达式到表达式“Getter”到“Setter”。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注——publicstaticActionGetSetter(Expression>getterExpression){/***SIMPLEPROPERTIESANDFIELDS***///check如果getter表达式直接引用PROPERTY或FIELDvarmemberAcessExpression=getterExpression.BodyasMemberExpression;if(memberAcessExpression!=null){//我们在这里分配属性或字段的SetValue方法ActionpropertyOrFieldSetValue=null;//属性varpropertyInfo=memberAcessExpression.MemberasPropertyInfo;if(propertyInfo!=null){propertyOrFieldSetValue=(declaringObjectInstance,property=OrFieldue)propertyInfo.SetValue(declaringObjectInstance,propertyOrFieldValue);};//字段varfieldInfo=memberAcessExpression.MemberasFieldInfo;if(fieldInfo!=null){propertyOrFieldSetValue=(declaringObjectInstance,propertyOrFieldValue)=>fieldInfo.SetValue(declaringObjectInstance,propertyOrFieldValue);}//这是获取声明对象实例的表达式。//示例:对于表达式“o=>o.Property1.Property2.CollectionProperty[3].TargetProperty”,它为我们提供了“o.Property1.Property2.CollectionProperty[3]”部分varmemberAcessExpressionCompiledLambda=Expression.Lambda(memberAcessExpression.Expression,getterExpression.Parameters.Single().Compile();Actionsetter=(expressionParameter,value)=>{//获取我们要设置属性的对象实例vardeclaringObjectInstance=memberAcessExpressionCompiledLambda.DynamicInvoke(expressionParameter);Debug.Assert(propertyOrFieldSetValue!=null,"propertyOrFieldSetValue!=null");//设置属性的值propertyOrFieldSetValue(declaringObjectInstance,value);};返回设置器;}/***集合(IDictionary和IList)***//**字典:*示例表达式:*"myObj=>myObj.Property1.ListProperty[5].AdditionalInfo["KEY"]"*Setter行为:*与添加到字典中相同。*它确实将Add("KEY",)添加到字典中。如果jey已经存在,它会失败。***LIST*示例表达式:*"myObj=>myObj.Property1.ListProperty[INDEX]"*Setter行为:*如果INDEX>=0并且索引存在于集合中,它的行为与插入集合相同。*IFINDEX)){//创建一个动作,它接受“dictionarrygetter”表达式所针对的对象的实例和一个值//要添加到字典中。动作dictionaryAdder=(expressionParameter,value)=>{try{vardictionaryInstance=(IDictionary)collectionGetterCompiledLambda.DynamicInvoke(expressionParameter);dictionaryInstance.Add(collectionKey,value);}catch(Exceptionexception){thrownewException(string.Format("添加到字典失败[Key='{0}',Value='{1}']。"adder"是从getter表达式生成的:'{2}'.",collectionKey,value,getterExpression.ToString()),异常);}};返回字典加法器;}//ILISTif(typeof(IList).MakeGenericType(typeof(bool)).IsAssignableFrom(collectionType.GetGenericTypeDefinition().MakeGenericType(typeof(bool)))){//创建一个接受对象实例的动作“collectiongetter”表达式用于插入一个值//ActioncollectionInserter=(expressionParameter,value)=>{try{varcollectionIndexFromExpression=int.Parse(collectionKey.ToString());//集合setter的语义是如果表达式中的索引<0则添加值,如果索引>=0则将项目设置在索引处。if(collectionIndexFromExpression)本文采集自网络,不代表立场,如涉及侵权,请点击右边联系管理员删除。

最新推荐
猜你喜欢