創建具有運行時指定數量參數的委託的簡單示例。我認爲這幾乎是無用的(因爲你必須通過DynamicInvoke
調用委託...你沒有任何安全性,而且你正在使用最慢的反射執行方法)。
public static Delegate CreateLambda(int num)
{
var parameters = new ParameterExpression[num];
for (int i = 0; i < num; i++)
{
parameters[i] = Expression.Parameter(typeof(int), "p" + i);
}
// We sum all the parameters together
Expression sum = parameters[0];
for (int i = 1; i < num; i++)
{
sum = Expression.Add(sum, parameters[i]);
}
Expression body = sum;
LambdaExpression exp = Expression.Lambda(body, parameters);
return exp.Compile();
}
的Expression.Lambda
意願真理genete一個Expression<Func<...>>
(或Expression<Action<...>>
),其中Func<...>
是基於給出的參數計算出的,但Expression<...>
是LambdaExpression
一個子類。如果Func<>
或Action<>
的參數太多,則即使在運行時也會生成委託類型。
然後:
int num = 5;
Delegate del = CreateLambda<double>(num);
// Note that we have to convert to object the various parameters,
// because DynamicInvoke uses a object[]
object[] values = Enumerable.Range(1, num).Select(x => (object)(double)x).ToArray();
double result = (double)del.DynamicInvoke(values);
Console.WriteLine("{0}={1}", string.Join("+", values), result);
如果你想有一個Func<T[], T>
它是可能的(並且可能是一個更好的主意):
public static Func<T[], T> CreateLambda<T>(int num)
{
var parameter = Expression.Parameter(typeof(T[]), "p");
// We sum all the parameters together
Expression sum = Expression.ArrayIndex(parameter, Expression.Constant(0));
for (int i = 1; i < num; i++)
{
sum = Expression.Add(sum, Expression.ArrayIndex(parameter, Expression.Constant(i)));
}
Expression body = sum;
var exp = Expression.Lambda<Func<T[], T>>(body, parameter);
return exp.Compile();
}
您只需使用Expression.ArrayIndex()
。
再比如說:
int num = 5;
Func<double[], double> del = CreateLambda<double>(num);
double[] values = Enumerable.Range(1, num).Select(x => (double)x).ToArray();
double result = del(values);
Console.WriteLine("{0}={1}", string.Join("+", values), result);
什麼只是Expression.Lambda(...)? –
表達式。Lambda是我用來從前面的操作中形成的表達式tress創建委託或者作爲參數傳遞給其他函數的API函數,我沒有在這裏展示,我只是使用表達式樹存儲的表達式樹變量ruleExpression –
我也嘗試了Plain.Lamda –