创建表达式以使用out参数调用方法

时间:2010-06-30 03:41:11

标签: c# expression

我正在尝试创建一个调用内部方法的表达式,内部方法有一个out参数,这可能吗?

public class Program
{
    static void Main(string[] args)
    {
        var type = typeof (Program);
        var methodInfo = type.GetMethod("ValidateActiveControl", BindingFlags.Instance | BindingFlags.NonPublic);

        var p1 = Expression.Parameter(type, "program");
        var p2 = Expression.Parameter(typeof (bool), "validatedControlAllowsFocusChange");

        var invokeExpression = Expression.Call(p1, methodInfo, p2);
        var func = (Func<Program,bool, bool>)Expression.Lambda(invokeExpression, p1, p2).Compile();

        var validatedControlAllowsFocusChange = true;
        // I would expect validatedControlAllowsFocusChange to be false after execution...
        Console.WriteLine(func.Invoke(new Program(), validatedControlAllowsFocusChange));
        Console.WriteLine(validatedControlAllowsFocusChange);

    }

    internal bool ValidateActiveControl(out bool validatedControlAllowsFocusChange)
    {
        validatedControlAllowsFocusChange = false;

        // Some code here...

        return true;
    }
}

2 个答案:

答案 0 :(得分:10)

除了Jim关于MakeByRefType的观点之外,您还需要创建自定义委托类型,因为Func不支持ref或out参数。把它们放在一起:

delegate bool ValidateDelegate(Program program, out bool validatedControlAllowsFocusChange);

static void Main(string[] args)
{
    var type = typeof(Program);
    var methodInfo = type.GetMethod("ValidateActiveControl", BindingFlags.Instance | BindingFlags.NonPublic);

    var p1 = Expression.Parameter(type, "program");
    var p2 = Expression.Parameter(typeof(bool).MakeByRefType(), "validatedControlAllowsFocusChange");

    var invokeExpression = Expression.Call(p1, methodInfo, p2);
    var func = Expression.Lambda<ValidateDelegate>(invokeExpression, p1, p2).Compile();

    var validatedControlAllowsFocusChange = true;
    // I would expect validatedControlAllowsFocusChange to be false after execution...
    Console.WriteLine(func.Invoke(new Program(), out validatedControlAllowsFocusChange));
    Console.WriteLine(validatedControlAllowsFocusChange);

}

编辑:这适用于.NET 4.0,但不适用于.NET 3.5。 3.5 Framework似乎不支持带有out或ref参数的lambda表达式树。这段代码:

delegate void RefTest(out bool test);

static void Main(string[] args)
{
    var p1 = Expression.Parameter(typeof(bool).MakeByRefType(), "test");
    var func = Expression.Lambda<RefTest>(Expression.Constant(null), p1);
}

抛出ArgumentException“lambda表达式不能包含传递引用参数”。如果不升级到.NET 4.0,我认为你不能做你想做的事。

答案 1 :(得分:1)

根据this blog post,你需要这样做:

typeof(bool).MakeByRefType();