作者:martinsleibert_471 | 来源:互联网 | 2023-06-15 15:41
以下代码仅适用于没有引用参数的调用方法。
public delegate void testD2(params object[] args);
public static testD2 SetTestD2(MethodInfo method)
{
ParameterExpression param = Expression.Parameter(typeof(object[]),"args");
ParameterInfo[] paramsInfo = method.GetParameters();
Expression[] argsExp = new Expression[paramsInfo.Length];
for (int i = 0; i {
Expression index = Expression.Constant(i);
Type paramType = paramsInfo[i].ParameterType;
//??? ByRef removed from type,becuse Expression.Call with ByRef parametrs lead to compile error
if (paramType.IsByRef == true)
paramType = paramType.GetElementType();
//??? and for this reason is not change of parameters permanent
Expression paramaccessorExp = Expression.ArrayIndex(param,index);
Expression paramCastExp = Expression.Convert(paramaccessorExp,paramType);
argsExp[i] = paramCastExp;
}
var blockExp = Expression.Call(method,argsExp);
LambdaExpression result = Expression.Lambda(typeof(testD2),blockExp,param); //change in param?
return (testD2)result.Compile();
}
我正在考虑更改通过params
关键字传递的输入参数,或者为lambda创建新的参数,但是我不知道如何。
public class testCls
{
public void Test()
{
MethodInfo mi = typeof(XXX).GetMethod("TestMethod");
var compiledObject2 = XXX.SetTestD2(mi);
int k = 5;
compiledObject2(k); //k is not passed as ByRef
}
}
public static void TestMethod(ref int a)
{
a = a * a;
}
ref
或out
参数与params
不兼容,我认为这是基本语言或运行时限制。
要执行所需的操作,可以将其编译为正确类型的强类型委托。 Expression.GetDelegateType呼叫可以为您创建正确的类型;与params object[]
不同,可以有输出和参考参数。
,
强类型委托是一种方法,但是对于各种方法需要额外的代码。这就是为什么我尝试使用通用函数来创建通用委托的原因。
对于关键字params,我认为如果该函数被经典地调用DelegateSomeFunc(a,b,c,),则不会通过引用传递任何内容。但是,如果该函数由数组调用,则参数将通过引用传递。
int k = 5;
string b = "aa";
object[] objArr = { k,b };
compiledObject2(k,b); //parameters passed by value
compiledObject2(objArr); //array passed by reference (params don't need create new array?)
代表调用此功能
public static void TestMethod(ref int a,string text)
{
a = a * a;
}
理论上可以用函数创建委托,但是还有另一个问题-用表达式参数数组而不是表达式数组调用函数。
原始帖子中的上面的代码排了一行
var blockExp = Expression.Call(method,argsExp);
但是argsExp可能无法返回函数更改的参数。因此,我将输入参数写在局部表达式变量中,称为函数的函数可以更改,最后将更改后的值放在输入参数数组中。
public static Class1.testD2 SetTestD2(System.Reflection.MethodInfo method)
{
ParameterExpression param = Expression.Parameter(typeof(object[]),"args"); // Expression.Parameter(typeof(object[]),"args");
BinaryExpression[] byExp=null;
Expression[] argsExp = GetArgExp(method.GetParameters(),param,ref byExp);
ParameterExpression xxx = Expression.Variable(typeof(int));
ParameterExpression yyy = Expression.Variable(typeof(string));
var blockExp =
Expression.Block( new[] { xxx,yyy } //variables,Expression.Assign(xxx,argsExp[0]),Expression.Assign(yyy,argsExp[1]),Expression.Call(method,xxx,yyy),Expression.Assign(Expression.ArrayAccess(param,Expression.Constant(0)),Expression.Convert(xxx,typeof(object))) //change input param array
) ;
LambdaExpression result = Expression.Lambda(typeof(testD2),blockExp,param);
return (testD2)result.Compile();
}
该功能只是更改输入参数的示例。现在可以返回更改的参数。
MethodInfo mi = typeof(Class1).GetMethod("TestMethod");
var compiledObject2 = Class1.SetTestD2(mi);
int k = 5;
string b = "aa";
object[] objArr = { k,b); //no changes
compiledObject2(objArr); //objArr[0] changed
但是我不知道函数是否可以修改创建委托的通用委托。