Chr*_*tow 28 javascript c# transformation expression-trees
例如,如果你有一个这样的表达式:
Expression<Func<int, int>> fn = x => x * x;
Run Code Online (Sandbox Code Playgroud)
是否有任何东西会遍历表达式树并生成它?
"function(x) { return x * x; }"
Run Code Online (Sandbox Code Playgroud)
Tho*_*que 31
这可能并不容易,但是,这绝对是可行的.像Entity Framework或Linq to SQL这样的ORM将Linq查询转换为SQL,但实际上你可以从表达式树生成任何你想要的东西......
您应该实现一个ExpressionVisitor分析和转换表达式.
编辑:这是一个非常基本的实现,适用于您的示例:
Expression<Func<int, int>> fn = x => x * x;
var visitor = new JsExpressionVisitor();
visitor.Visit(fn);
Console.WriteLine(visitor.JavaScriptCode);
...
class JsExpressionVisitor : ExpressionVisitor
{
private readonly StringBuilder _builder;
public JsExpressionVisitor()
{
_builder = new StringBuilder();
}
public string JavaScriptCode
{
get { return _builder.ToString(); }
}
public override Expression Visit(Expression node)
{
_builder.Clear();
return base.Visit(node);
}
protected override Expression VisitParameter(ParameterExpression node)
{
_builder.Append(node.Name);
base.VisitParameter(node);
return node;
}
protected override Expression VisitBinary(BinaryExpression node)
{
base.Visit(node.Left);
_builder.Append(GetOperator(node.NodeType));
base.Visit(node.Right);
return node;
}
protected override Expression VisitLambda<T>(Expression<T> node)
{
_builder.Append("function(");
for (int i = 0; i < node.Parameters.Count; i++)
{
if (i > 0)
_builder.Append(", ");
_builder.Append(node.Parameters[i].Name);
}
_builder.Append(") {");
if (node.Body.Type != typeof(void))
{
_builder.Append("return ");
}
base.Visit(node.Body);
_builder.Append("; }");
return node;
}
private static string GetOperator(ExpressionType nodeType)
{
switch (nodeType)
{
case ExpressionType.Add:
return " + ";
case ExpressionType.Multiply:
return " * ";
case ExpressionType.Subtract:
return " - ";
case ExpressionType.Divide:
return " / ";
case ExpressionType.Assign:
return " = ";
case ExpressionType.Equal:
return " == ";
case ExpressionType.NotEqual:
return " != ";
// TODO: Add other operators...
}
throw new NotImplementedException("Operator not implemented");
}
}
Run Code Online (Sandbox Code Playgroud)
它只使用单个指令处理lambda,但无论如何C#编译器都不能为块lambda生成表达式树.
仍然有很多工作要做,当然,这是一个很小的实现......你可能需要添加方法调用(VisitMethodCall),属性和字段访问(VisitMember)等.