表达式来; Func键<的TModel,串>>为表达<作用<&的TModel GT;> "

编程入门 行业动态 更新时间:2024-10-26 12:28:22
本文介绍了表达式来; Func键<的TModel,串>>为表达<作用<&的TModel GT;> "吸气"到"二传手"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我是新来的表情,我想知道如何,如果它在任何可能的方式来转换自己的表情。

I'm new to expressions, and i'd like to know how if it's in any way possible to convert my expression

让我们在这个例子中我的TModel说是类型的客户,在某处指定它是这样的:

Let's say in this example my TModel is of type Customer, and assigned it somewhere like this:

Expression<Func<TModel, string>> getvalueexpression = customer =>customer.Name

要像

Expression<Action<TModel,string>> setvalueexpression = [PSEUDOCODE] getvalueexpression = input Action<TModel,string> Setter = setvalueexpression.Compile(); Setter(mycustomer,value);

因此​​,在短期,我想以某种方式建立和编译设置由指定的客户名称的表达式我吸气的表达,为特定值。

So in short, i want to somehow build and compile an expression that sets the customer name specified by my getter expression, to a specific value.

推荐答案

修改版本。这个类可能是更好的比许多其他的你可以找到身边:-)这是因为该版本支持直接属性( P => PB )(其他人一样: - )),嵌套属性( p => PBCD ),田野(包括终端和中间,所以在 p => ; PBCD 两者 B 和 D 可能是场)和类型的内部铸造(所以 p =>((B型)PB).CD 和 p =>(PB为B型).CD)。不支持的唯一的事情是铸造终端元素(所以没有 P =>(对象)p.B )。

Modified version. This class is probably better than many other ones you can find around :-) This is because this version support direct properties (p => p.B) (as everyone else :-) ), nested properties (p => p.B.C.D), fields (both "terminal" and "in the middle", so in p => p.B.C.D both B and D could be fields) and "inner" casting of types (so p => ((BType)p.B).C.D and p => (p.B as BType).C.D). The only thing that isn't supported is casting of the "terminal" element (so no p => (object)p.B).

有两个codepaths中的发电机:简单的表达式( P => PB )和嵌套的表达。有针对.NET 4.0的代码的变种(即有 Expression.Assign 表达式类型)。从我的一些基准测试速度最快的代表是:字段的简单 Delegate.CreateDelegate 房产, Expression.Assign 和简单 FieldSetter 字段的(这是只比 Expression.Assign 慢一点的字段)。所以在.NET 4.0,你应该带走所有标记为3.5的代码。

There are two "codepaths" in the generator: for simple Expressions (p => p.B) and for "nested" expressions. There are code variants for .NET 4.0 (that has the Expression.Assign expression type). From some benchmarks of mine the fastest delegates are: "simple" Delegate.CreateDelegate for properties, Expression.Assign for fields and "simple" FieldSetter for fields (this one is just a little slower than Expression.Assign for fields). So under .NET 4.0 you should take away all the code marked as 3.5.

部分是不是我的。最初的(简单)版本是基于功能NHibernate代码(但它仅支持直接属性),其他一些地方基于从的如何在C#中的表达式树设置字段值?并的分配在.NET 3.5表达式树

Part of the code isn't mine. The initial (simple) version was based on the Fluent NHibernate code (but it supported only direct properties), some other parts are based on code from How do I set a field value in an C# Expression tree? and Assignment in .NET 3.5 expression trees.

public static class FluentTools { public static Action<T, TValue> GetterToSetter<T, TValue>(Expression<Func<T, TValue>> getter) { ParameterExpression parameter; Expression instance; MemberExpression propertyOrField; GetMemberExpression(getter, out parameter, out instance, out propertyOrField); // Very simple case: p => p.Property or p => p.Field if (parameter == instance) { if (propertyOrField.Member.MemberType == MemberTypes.Property) { // This is FASTER than Expression trees! (5x on my benchmarks) but works only on properties PropertyInfo property = propertyOrField.Member as PropertyInfo; MethodInfo setter = property.GetSetMethod(); var action = (Action<T, TValue>)Delegate.CreateDelegate(typeof(Action<T, TValue>), setter); return action; } #region .NET 3.5 else // if (propertyOrField.Member.MemberType == MemberTypes.Field) { // 1.2x slower than 4.0 method, 5x faster than 3.5 method FieldInfo field = propertyOrField.Member as FieldInfo; var action = FieldSetter<T, TValue>(field); return action; } #endregion } ParameterExpression value = Expression.Parameter(typeof(TValue), "val"); Expression expr = null; #region .NET 3.5 if (propertyOrField.Member.MemberType == MemberTypes.Property) { PropertyInfo property = propertyOrField.Member as PropertyInfo; MethodInfo setter = property.GetSetMethod(); expr = Expression.Call(instance, setter, value); } else // if (propertyOrField.Member.MemberType == MemberTypes.Field) { expr = FieldSetter(propertyOrField, value); } #endregion //#region .NET 4.0 //// For field access it's 5x faster than the 3.5 method and 1.2x than "simple" method. For property access nearly same speed (1.1x faster). //expr = Expression.Assign(propertyOrField, value); //#endregion return Expression.Lambda<Action<T, TValue>>(expr, parameter, value).Compile(); } private static void GetMemberExpression<T, U>(Expression<Func<T, U>> expression, out ParameterExpression parameter, out Expression instance, out MemberExpression propertyOrField) { Expression current = expression.Body; while (current.NodeType == ExpressionType.Convert || current.NodeType == ExpressionType.TypeAs) { current = (current as UnaryExpression).Operand; } if (current.NodeType != ExpressionType.MemberAccess) { throw new ArgumentException(); } propertyOrField = current as MemberExpression; current = propertyOrField.Expression; instance = current; while (current.NodeType != ExpressionType.Parameter) { if (current.NodeType == ExpressionType.Convert || current.NodeType == ExpressionType.TypeAs) { current = (current as UnaryExpression).Operand; } else if (current.NodeType == ExpressionType.MemberAccess) { current = (current as MemberExpression).Expression; } else { throw new ArgumentException(); } } parameter = current as ParameterExpression; } #region .NET 3.5 // Based on stackoverflow/questions/321650/how-do-i-set-a-field-value-in-an-c-expression-tree/321686#321686 private static Action<T, TValue> FieldSetter<T, TValue>(FieldInfo field) { DynamicMethod m = new DynamicMethod("setter", typeof(void), new Type[] { typeof(T), typeof(TValue) }, typeof(FluentTools)); ILGenerator cg = m.GetILGenerator(); // arg0.<field> = arg1 cg.Emit(OpCodes.Ldarg_0); cg.Emit(OpCodes.Ldarg_1); cg.Emit(OpCodes.Stfld, field); cg.Emit(OpCodes.Ret); return (Action<T, TValue>)m.CreateDelegate(typeof(Action<T, TValue>)); } // Based on stackoverflow/questions/208969/assignment-in-net-3-5-expression-trees/3972359#3972359 private static Expression FieldSetter(Expression left, Expression right) { return Expression.Call( null, typeof(FluentTools) .GetMethod("AssignTo", BindingFlags.NonPublic | BindingFlags.Static) .MakeGenericMethod(left.Type), left, right); } private static void AssignTo<T>(ref T left, T right) // note the 'ref', which is { // important when assigning left = right; // to value types! } #endregion }

更多推荐

表达式来; Func键&LT;的TModel,串&GT;&GT;为表达&lt;作用&LT;&的TModel GT

本文发布于:2023-11-10 00:35:16,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1573874.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:表达式   作用   二传   amp   Func

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!