C# 动态构建函数<;Tn,T>;具有使用表达式的动态实体

C# 动态构建函数<;Tn,T>;具有使用表达式的动态实体,c#,dynamic,delegates,expression,func,C#,Dynamic,Delegates,Expression,Func,注意:Func=可以是任意数量的类型 我最近接了一个我已经工作了一段时间的项目,正在审核代码。在我休息之前,我被一个方法的实施激怒了,所以我花了大约2天的时间来尝试改进它。我正在尝试使用运行时已知的泛型类型参数count、type和return type动态创建一个Func 我现在使用的代码块是以下switch语句:(对不起,格式不正确) 或: var paramCount=member.GetParameters().Count(); 如果(paramCount==0) method=newf

注意:
Func
=可以是任意数量的类型

我最近接了一个我已经工作了一段时间的项目,正在审核代码。在我休息之前,我被一个方法的实施激怒了,所以我花了大约2天的时间来尝试改进它。我正在尝试使用运行时已知的泛型类型参数count、type和return type动态创建一个
Func

我现在使用的代码块是以下switch语句:(对不起,格式不正确)

或:

var paramCount=member.GetParameters().Count();
如果(paramCount==0)
method=newfunc(()=>member.Invoke(LinkedDocument,null));
else if(paramCount==1)
method=newfunc(param=>member.Invoke(LinkedDocument,new[]{param}));
其他的
方法=新函数(
param=>member.Invoke(
LinkedDocument,param));
哪个有效。。。但是我只是认为可以更动态地涵盖所有方法

  • 获取参数表达式的列表。为此,我调用GetParameters,然后使用Select和ToList将ParameterInfo转换为ParameterExpression
  • 创建表达式以使用参数调用方法
  • 确定您的委托类型。看起来您对此有一个工作方法,但我也在下面包含了我的代码
  • 创建一个lambda表达式,传入委托类型、要调用方法的表达式(这是lambda表达式的主体)和参数
  • 将“method”设置为lambda表达式的编译版本
  • 对代理执行任何您想要的操作
  • 代码:

    下面是我用来获取委托/func类型的代码

    public static Type[] _baseFuncTypes = new Type[] { typeof(Func<>), typeof(Func<,>), typeof(Func<,,>), typeof(Func<,,,>), typeof(Func<,,,,>), typeof(Func<,,,,,>), typeof(Func<,,,,,,>), typeof(Func<,,,,,,,>), typeof(Func<,,,,,,,,>) };
    
    private static Type GetFuncType(Type[] parameterTypes, Type returnType)
    {
        Array.Resize(ref parameterTypes, parameterTypes.Length + 1);
        parameterTypes[parameterTypes.Length - 1] = returnType;
    
        return _baseFuncTypes[parameterTypes.Length - 1].MakeGenericType(parameterTypes);
    }
    
    public static Type[]\u baseFuncTypes=new Type[]{typeof(Func)、typeof(Func)、typeof(Func)、typeof(Func)、typeof(Func)、typeof(Func)、typeof(Func)};
    私有静态类型GetFuncType(类型[]参数类型,类型returnType)
    {
    Array.Resize(ref parameterTypes,parameterTypes.Length+1);
    parameterTypes[parameterTypes.Length-1]=返回类型;
    返回_baseFuncTypes[parameterTypes.Length-1].MakeGenericType(parameterTypes);
    }
    
    Invokemethod.是的,我是否从代码中正确地理解了所有不同的委托实际上只是对eversame
    obj.Invoke的调用。它们都是我通过反射获取的类方法。我把前面的循环放在问题里。啊,我看到你的编辑了。现在它更有意义了……对不起,我看错了你的回答。我使用不同数量的参数调用多个方法。请参阅更新。我使用
    obj
    所在的循环进行了更新。当您将不同的委托存储在initalScope中时,如何确保始终将每个特定委托的正确数量的参数传递给该委托?
    var assem = System.Reflection.Assembly.GetAssembly(typeof(Func<object>));
    var type = assem.GetType(string.Format("Func`{0}", obj.GetParameters().Count()));
    var typeArr = obj.GetParameters().Select(param => param.ParameterType).ToList();
    typeArr.Add(obj.ReturnType);
    
    var ctrInfo = type.GetConstructor(typeArr.ToArray());
    var expType = Expression.New(type);
    
    switch (member.GetParameters().Count())
    {
        case 0:
            method = new Func<dynamic>(() => member.Invoke(LinkedDocument, null));
            break;
        case 1:
            method = new Func<object, dynamic>(param => member.Invoke(LinkedDocument, new[] { param }));
            break;
        default:
            method = new Func<object[], dynamic>(
                param => member.Invoke(
                    LinkedDocument, param));
            break;
    }
    
    var paramCount = member.GetParameters().Count();
    if(paramCount == 0)
        method = new Func<dynamic>(() => member.Invoke(LinkedDocument, null));
    else if(paramCount == 1)
        method = new Func<object, dynamic>(param => member.Invoke(LinkedDocument, new[] { param }));
    else
        method = new Func<object[], dynamic>(
               param => member.Invoke(
                   LinkedDocument, param));
    
    foreach (var member in LinkedDocument.GetType()
                           .GetMethods()
                           .Where(
                               method =>
                                   method.GetCustomAttributes(
                                       typeof(ScriptingMethodAttribute), true)
                                         .Length != 0))
    {
        var parameters = member.GetParameters().Select(v => Expression.Parameter(v.ParameterType, v.Name)).ToList();
        var caller = Expression.Call(member, parameters);
        var delegateType = GetFuncType(member.GetParameters().Select(v => v.ParameterType).ToArray(), member.ReturnType);
        var methodLambda = Expression.Lambda(delegateType, caller, parameters);
    
        Delegate method = methodLambda.Compile();
    
        initalScope.Add(member.Name.ToLower(), method);
    }
    
    public static Type[] _baseFuncTypes = new Type[] { typeof(Func<>), typeof(Func<,>), typeof(Func<,,>), typeof(Func<,,,>), typeof(Func<,,,,>), typeof(Func<,,,,,>), typeof(Func<,,,,,,>), typeof(Func<,,,,,,,>), typeof(Func<,,,,,,,,>) };
    
    private static Type GetFuncType(Type[] parameterTypes, Type returnType)
    {
        Array.Resize(ref parameterTypes, parameterTypes.Length + 1);
        parameterTypes[parameterTypes.Length - 1] = returnType;
    
        return _baseFuncTypes[parameterTypes.Length - 1].MakeGenericType(parameterTypes);
    }