Stu*_*art 5 c# reflection expression
我目前正在尝试编写一些代码,将C#表达式转换为文本。
为此,我不仅需要遍历“表达式”树,还需要对其进行一小部分评估-以获得局部变量的当前值。
我发现很难用文字表达,因此这里是伪代码。缺少的部分在第一种方法中:
public class Program
{
private static void DumpExpression(Expression expression)
{
// how do I dump out here some text like:
// set T2 = Perform "ExternalCalc" on input.T1
// I can easily get to:
// set T2 = Perform "Invoke" on input.T1
// but how can I substitute Invoke with the runtime value "ExternalCalc"?
}
static void Main(string[] args)
{
var myEvaluator = new Evaluator() {Name = "ExternalCalc"};
Expression<Func<Input, Output>> myExpression = (input) => new Output() {T2 = myEvaluator.Invoke(input.T1)};
DumpExpression(myExpression);
}
}
class Evaluator
{
public string Name { get; set; }
public string Invoke(string input)
{
throw new NotImplementedException("Never intended to be implemented");
}
}
class Input
{
public string T1 { get; set; }
}
class Output
{
public string T2 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我已经开始使用以下代码进行调查:
foreach (MemberAssignment memberAssignment in body.Bindings)
{
Console.WriteLine("assign to {0}", memberAssignment.Member);
Console.WriteLine("assign to {0}", memberAssignment.BindingType);
Console.WriteLine("assign to {0}", memberAssignment.Expression);
var expression = memberAssignment.Expression;
if (expression is MethodCallExpression)
{
var methodCall = expression as MethodCallExpression;
Console.WriteLine("METHOD CALL: " + methodCall.Method.Name);
Console.WriteLine("METHOD CALL: " + expression.Type.Name);
var target = methodCall.Object;
// ?
}
}
Run Code Online (Sandbox Code Playgroud)
但是一旦达到那个MethodCallExpression级别,我就会对如何解析它以及如何获取实际实例感到迷失。
非常感谢任何有关如何执行此操作的指示/建议。
解析表达式树...复杂且耗时。这是一个非常不完整的版本,仅能处理您的示例。特别要注意的是,我们需要:
输出:
新的输出将 T2 设置为:调用ExternalCalc,从 capture-context 获取 myEvaluator,输入 = 从 @input 获取 T1
代码:
private static void DumpExpression(Expression expression)
{
var sb = new StringBuilder();
Walk(expression, sb);
string s = sb.ToString();
}
static object Evaluate(Expression expr)
{
switch (expr.NodeType)
{
case ExpressionType.Constant:
return ((ConstantExpression)expr).Value;
case ExpressionType.MemberAccess:
var me = (MemberExpression)expr;
object target = Evaluate(me.Expression);
switch (me.Member.MemberType)
{
case System.Reflection.MemberTypes.Field:
return ((FieldInfo)me.Member).GetValue(target);
case System.Reflection.MemberTypes.Property:
return ((PropertyInfo)me.Member).GetValue(target, null);
default:
throw new NotSupportedException(me.Member.MemberType.ToString());
}
default:
throw new NotSupportedException(expr.NodeType.ToString());
}
}
static void Walk(Expression expr, StringBuilder output)
{
switch (expr.NodeType)
{
case ExpressionType.New:
var ne = (NewExpression)expr;
var ctor = ne.Constructor;
output.Append(" a new ").Append(ctor.DeclaringType.Name);
if(ne.Arguments != null && ne.Arguments.Count != 0)
{
var parameters = ctor.GetParameters();
for(int i = 0 ;i < ne.Arguments.Count ; i++)
{
output.Append(i == 0 ? " with " : ", ")
.Append(parameters[i].Name).Append(" =");
Walk(ne.Arguments[i], output);
}
}
break;
case ExpressionType.Lambda:
Walk(((LambdaExpression)expr).Body, output);
break;
case ExpressionType.Call:
var mce = (MethodCallExpression)expr;
if (mce.Method.DeclaringType == typeof(Evaluator))
{
object target = Evaluate(mce.Object);
output.Append(" call ").Append(((Evaluator)target).Name);
}
else
{
output.Append(" call ").Append(mce.Method.Name);
}
if (mce.Object != null)
{
output.Append(" on");
Walk(mce.Object, output);
}
if (mce.Arguments != null && mce.Arguments.Count != 0)
{
var parameters = mce.Method.GetParameters();
for (int i = 0; i < mce.Arguments.Count; i++)
{
output.Append(i == 0 ? " with " : ", ")
.Append(parameters[i].Name).Append(" =");
Walk(mce.Arguments[i], output);
}
}
break;
case ExpressionType.MemberInit:
var mei = (MemberInitExpression)expr;
Walk(mei.NewExpression, output);
foreach (var member in mei.Bindings)
{
switch(member.BindingType) {
case MemberBindingType.Assignment:
output.Append(" set ").Append(member.Member.Name)
.Append(" to:");
Walk(((MemberAssignment)member).Expression, output);
break;
default:
throw new NotSupportedException(member.BindingType.ToString());
}
}
break;
case ExpressionType.Constant:
var ce = (ConstantExpression)expr;
if (Attribute.IsDefined(ce.Type, typeof(CompilerGeneratedAttribute)))
{
output.Append(" capture-context");
}
else
{
output.Append(" ").Append(((ConstantExpression)expr).Value);
}
break;
case ExpressionType.MemberAccess:
var me = (MemberExpression)expr;
output.Append(" get ").Append(me.Member.Name).Append(" from");
if (me.Expression == null)
{ // static
output.Append(me.Member.DeclaringType.Name);
}
else
{
Walk(me.Expression, output);
}
break;
case ExpressionType.Parameter:
var pe = (ParameterExpression)expr;
output.Append(" @").Append(pe.Name);
break;
default:
throw new NotSupportedException(expr.NodeType.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
983 次 |
| 最近记录: |