문제
표현식 트리에 과제를 인코딩 할 수 있습니까?
해결책
아니, 난 그렇게 믿지 않는다.
확실히 C# 컴파일러는 Lambda 표현식을 변환 할 때이를 방해합니다.
int x;
Expression<Func<int,int>> foo = (x=y); // Assign to x and return value
오류가 발생합니다.
CS0832: An expression tree may not contain an assignment operator
다른 팁
.NET 4.0 라이브러리로 수행 할 수 있어야합니다. microsoft.scripting.core.dll을 .net 3.5 프로젝트로 가져옵니다.
DLR 0.9를 사용하고 있습니다 - Expession.Block 및 expression.scope에 약간의 변경 사항이있을 수 있습니다. http://www.codeplex.com/dlr/thread/view.aspx?threadid=43234)
다음 샘플은 당신을 보여주는 것입니다.
using System;
using System.Collections.Generic;
using Microsoft.Scripting.Ast;
using Microsoft.Linq.Expressions;
using System.Reflection;
namespace dlr_sample
{
class Program
{
static void Main(string[] args)
{
List<Expression> statements = new List<Expression>();
ParameterExpression x = Expression.Variable(typeof(int), "r");
ParameterExpression y = Expression.Variable(typeof(int), "y");
statements.Add(
Expression.Assign(
x,
Expression.Constant(1)
)
);
statements.Add(
Expression.Assign(
y,
x
)
);
MethodInfo cw = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
statements.Add(
Expression.Call(
cw,
y
)
);
LambdaExpression lambda = Expression.Lambda(Expression.Scope(Expression.Block(statements), x, y));
lambda.Compile().DynamicInvoke();
Console.ReadLine();
}
}
}
정확하게 수행하기위한 내 확장 방법 :
/// <summary>
/// Provides extensions for converting lambda functions into assignment actions
/// </summary>
public static class ExpressionExtenstions
{
/// <summary>
/// Converts a field/property retrieve expression into a field/property assign expression
/// </summary>
/// <typeparam name="TInstance">The type of the instance.</typeparam>
/// <typeparam name="TProp">The type of the prop.</typeparam>
/// <param name="fieldGetter">The field getter.</param>
/// <returns></returns>
public static Expression<Action<TInstance, TProp>> ToFieldAssignExpression<TInstance, TProp>
(
this Expression<Func<TInstance, TProp>> fieldGetter
)
{
if (fieldGetter == null)
throw new ArgumentNullException("fieldGetter");
if (fieldGetter.Parameters.Count != 1 || !(fieldGetter.Body is MemberExpression))
throw new ArgumentException(
@"Input expression must be a single parameter field getter, e.g. g => g._fieldToSet or function(g) g._fieldToSet");
var parms = new[]
{
fieldGetter.Parameters[0],
Expression.Parameter(typeof (TProp), "value")
};
Expression body = Expression.Call(AssignmentHelper<TProp>.MethodInfoSetValue,
new[] {fieldGetter.Body, parms[1]});
return Expression.Lambda<Action<TInstance, TProp>>(body, parms);
}
public static Action<TInstance, TProp> ToFieldAssignment<TInstance, TProp>
(
this Expression<Func<TInstance, TProp>> fieldGetter
)
{
return fieldGetter.ToFieldAssignExpression().Compile();
}
#region Nested type: AssignmentHelper
private class AssignmentHelper<T>
{
internal static readonly MethodInfo MethodInfoSetValue =
typeof (AssignmentHelper<T>).GetMethod("SetValue", BindingFlags.NonPublic | BindingFlags.Static);
private static void SetValue(ref T target, T value)
{
target = value;
}
}
#endregion
}
Jon Skeet과 Traumapony가 이미 말했듯이 Expression.Assign
.NET 4 이전에는 사용할 수 없습니다.이 누락 된 비트를 둘러싼 방법에 대한 또 다른 구체적인 예는 다음과 같습니다.
public static class AssignmentExpression
{
public static Expression Create(Expression left, Expression right)
{
return
Expression.Call(
null,
typeof(AssignmentExpression)
.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!
}
}
그런 다음 간단히 전화하십시오 AssignmentExpression.Create()
대신에 Expression.Assign()
.
당신은 아마도 표현 나무를 사용하여 일할 수 있습니다. 인수는 양수인의 가치 인 Lambda 기능을 호출하십시오.
제휴하지 않습니다 StackOverflow