设置任何Func <>的参数

我有一个func ,Func ,func 等任何func类型的对象。我想用一个恒定值替换其中一个输入参数。

例如:

object SetParameter<T>(object function,int index,T value){
    //I don't know how to code this.
}

Func<int,String,String> function = (a,b) => a.ToString() + b;
object objectFunction = function;
object newFunction = SetParameter<int>(objectFunction,5);
// Here the new function should be a Func<String,String> which value "(b) => function(5,b)"

我现在已经如何获取结果函数的类型,但这并不能真正帮助我实现所需的行为:

private Type GetNewFunctionType<T>(object originalFunction,T value)
{
    Type genericType = originalFunction.GetType();

    if (genericType.IsGenericType)
    {
        var types = genericType.GetGenericArguments().ToList();
        types.RemoveAt(index);
        Type genericTypeDefinition = genericType.GetGenericTypeDefinition();
        return genericTypeDefinition.MakeGenericType(types.ToArray());
    }

    throw new InvalidOperationException($"{nameof(originalFunction)} must be a generic type");
}
a642975818 回答:设置任何Func <>的参数

尚不清楚转换的目的是什么,但是避免所有反射不是很容易。例如:

Func<int,string,string> func3 = (a,b) => a.ToString() + b;

Func<string,string> func3withConst = (b) => func3(10,b);

由于您所讨论的范围非常有限(仅支持Func<TReturn>Func<T1,TReturn>Func<T1,T2,TReturn>),通过反射进行此操作更容易出错,也更难阅读。

,

以防万一您需要use expression tree to build the function

object SetParameter<T>(object function,int index,T value)
{
    var parameterTypes = function.GetType().GetGenericArguments();

    // Skip where i == index
    var newFuncParameterTypes = parameterTypes.SkipWhile((_,i) => i == index).ToArray();

    // Let's assume function is Fun<,> to make this example simple :)
    var newFuncType = typeof(Func<,>).MakeGenericType(newFuncParameterTypes);

    // Now build a new function using expression tree.
    var methodCallParameterTypes = parameterTypes.Reverse().Skip(1).Reverse().ToArray();
    var methodCallParameters = methodCallParameterTypes.Select(
        (t,i) => i == index
            ? (Expression)Expression.Constant(value,typeof(T))
            : Expression.Parameter(t,"b")
        ).ToArray();

    // func.Invoke(5,b)
    var callFunction = Expression.Invoke(
        Expression.Constant(function),methodCallParameters);

    // b => func.Invoke(5,b)
    var newFunc = Expression.Lambda(
        newFuncType,callFunction,methodCallParameters.OfType<ParameterExpression>()
    ).Compile();

    return newFunc;
}

要使用此功能:

Func<int,string> func = (a,b) => a.ToString() + b;

var newFunc = (Func<string,string>)SetParameter<int>(func,5);

// Output: 5b
Console.WriteLine(newFunc("b"));
本文链接:https://www.f2er.com/2408291.html

大家都在问