C# 表达式树中的空传播

C# 表达式树中的空传播,c#,lambda,expression-trees,C#,Lambda,Expression Trees,请参见下面的示例代码。如何修改它以处理空值,类似于运算符的工作方式。运算符的工作方式 class Program { static LambdaExpression GetExpression(Expression<Func<string, string>> expr) { return expr; } static void Main(string[] args) { // I want to p

请参见下面的示例代码。如何修改它以处理空值,类似于
运算符的工作方式。
运算符的工作方式

class Program
{
    static LambdaExpression GetExpression(Expression<Func<string, string>> expr)
    {
        return expr;
    }

    static void Main(string[] args)
    {
        // I want to perform the following null propagation check
        // in the expression tree below.
        // (s as string)?.Replace("a", "o");

        var expr = GetExpression(t => t);

        var oldValue = Expression.Constant("a", typeof(string));
        var newValue = Expression.Constant("o", typeof(string));
        var mi = typeof(string).GetMethod(nameof(string.Replace), new[] { typeof(string), typeof(string) });

        var invoke = Expression.Invoke(expr, expr.Parameters);
        var call = Expression.Call(invoke, mi, oldValue, newValue);
        var lambda = Expression.Lambda(call, false, expr.Parameters);

        Console.WriteLine(lambda.Compile().DynamicInvoke("gaga"));

        // Should print empty line. Not throw!
        Console.WriteLine(lambda.Compile().DynamicInvoke(null));
    }
}
类程序
{
静态LambdaExpression GetExpression(表达式expr)
{
返回表达式;
}
静态void Main(字符串[]参数)
{
//我想执行以下空传播检查
//在下面的表达式树中。
//(s为字符串)?。替换(“a”、“o”);
var expr=GetExpression(t=>t);
var oldValue=表达式.常量(“a”,类型(字符串));
var newValue=表达式.常量(“o”,typeof(string));
var mi=typeof(string).GetMethod(nameof(string.Replace),new[]{typeof(string),typeof(string)});
var invoke=Expression.invoke(expr,expr.Parameters);
var call=Expression.call(invoke、mi、oldValue、newValue);
var lambda=Expression.lambda(调用,false,expr.Parameters);
Console.WriteLine(lambda.Compile().DynamicInvoke(“gaga”);
//应该打印空行。不要扔!
WriteLine(lambda.Compile().DynamicInvoke(null));
}
}

你必须做两件事:

  • 调用
    lambda.Compile().DynamicInvoke(null)
    是错误的

    文件说明,参数可以是:

    类型:System.Object[]:
    对象数组,这些对象是要传递给当前委托表示的方法的参数。
    -或-
    null,如果当前委托表示的方法不需要参数

    因此,通过传递null,您可以在不使用参数的情况下调用它,但希望使用null字符串参数进行调用:

    这就是为什么您应该将此行更改为
    lambda.Compile().DynamicInvoke(新对象[]{null})
    或干脆更改为
    lambda.Compile().DynamicInvoke((字符串)null)

  • 必须使用
    Expression.condition
    添加空条件

  • 最终代码:

    var expr = GetExpression(t => t);
    var oldValue = Expression.Constant("a", typeof(string));
    var newValue = Expression.Constant("o", typeof(string));
    var mi = typeof(string).GetMethod(nameof(string.Replace), new[] { typeof(string), typeof(string) });
    
    var invoke = Expression.Invoke(expr, expr.Parameters);
    var call = Expression.Call(invoke, mi, oldValue, newValue);
    
    ConstantExpression nullConst = Expression.Constant(null, typeof(string));
    var nullCondition = Expression.Condition(Expression.Equal(invoke, nullConst),
        nullConst, call);
    
    var lambda = Expression.Lambda(nullCondition, false, expr.Parameters);
    
    object result1 = lambda.Compile().DynamicInvoke("gaga"); // =="gogo"
    object result2 = lambda.Compile().DynamicInvoke((string) null); //== null
    
    Condition()
    是否也适用于
    void
    方法?例如,
    myList?.Clear()