Create expression to invoke method with out parameter
I am trying to create an expression that invokes an internal method, the internal method has an out parameter, is this possible?
public class Program
{
static void Main(string[] args)
{
var type = typeof (Program);
var methodInfo = type.GetMethod("ValidateActiveControl", BindingFlags.Instance | BindingFlags.NonPublic);
var p1 = Expression开发者_如何学C.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;
}
}
In addition to Jim's point about MakeByRefType, you will need to create a custom delegate type, since Func
does not support ref or out parameters. Putting it all together:
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);
}
Edit: This works in .NET 4.0, but not in .NET 3.5. The 3.5 Framework doesn't appear to support lambda expression trees with out or ref parameters. This code:
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);
}
throws an ArgumentException "A lambda expression cannot contain pass by reference parameters". I don't think you can do what you want without upgrading to .NET 4.0.
According to this blog post, you'd need to do:
typeof(bool).MakeByRefType();
精彩评论