gpt4 book ai didi

C# 在注入(inject)第一个参数的给定方法上创建 lambda

转载 作者:行者123 更新时间:2023-12-03 14:28:05 24 4
gpt4 key购买 nike

在 C# 中,我在给定的类(非静态)中定义了以下方法:

int MyMethod(ScriptEngine script, int a, int b) {
return a + b;
}

void MyMethod2(ScriptEngine script, string c) {
// do something with c
}
我想创建自动通过 ScriptEngine 的包装 lambda/Action/Delegate/MethodInfo (脚本引擎都接受)和 this从给定的预定义变量。
到目前为止,我已经尝试过:
// With overloads up to 16 template parameters
Action<T1> Wrap<T1>(Action<ScriptEngine, T1> func, ScriptEngine script) {
return (Action<T1>) ((t1) => func(script, t1));
}
但是当在 MyMethod2 上调用时,我得到了 The type arguments for method … cannot be inferred from the usage. Try specifying the type arguments explicitly .如果我明确指定模板参数,它可以工作,但我想避免这样的规范。
有没有其他方法(不是我的解决方案所必需的)我可以自动(或半自动)创建这样的包装器?
值得一提的是,有专门的抽象方法 void RegisterAll(ScriptEngine script)可以注册给定子类的必需成员。
这是我要实现的目标的示例:
class ScriptEngine { // Stub to have complete example, actual implementation is defined elsewhere
void RegisterApi(string name, MethodInfo methodInfo) { }
void RegisterApi(string name, Delegate delegateSelf) { }
}

class Api {
int MyMethod(ScriptEngine script, int a, int b) {
return a + b;
}

void MyMethod2(ScriptEngine script, string c) {
// do something with c
}

void RegisterAll(ScriptEngine script) {
// Is there any way to shorten this up (not providing MyMethod twice, not providing template arguments?)
script.RegisterApi(nameof(MyMethod), (Delegate)Wrap<string>(MyMethod, script));
}

}
问题是如何改进 RegisterApi方法所以它:
  • 方法只取一次
  • 不需要通过模板方法指定参数
  • 最佳答案

    实际上还有另一种不涉及发出新表达式的解决方案(在 iOS 上可能会失败!)
    首先,让我们定义以下包装器:

        private class Wrapper
    {
    public readonly object container;
    public readonly MethodInfo method;
    public readonly ScriptEngine engine;

    public Wrapper(object container, MethodInfo method, ScriptEngine engine)
    {
    this.container = container;
    this.method = method;
    this.engine = engine;
    }

    public Action CreateAction()
    {
    return () => method.Invoke(container, new object[] { engine });
    }
    public Action<T1> CreateAction<T1>()
    {
    return (arg1) => method.Invoke(container, new object[] { engine, arg1 });
    }
    // etc
    }
    现在你可以注册这样的方法:
            var type = typeof(Wrapper);
    var instance = Activator.CreateInstance(type, new object[] { container, methodInfo, engine });
    MethodInfo methodActual = null;
    if (methodInfo.ReturnType == typeof(void))
    {
    var methods = type.GetMethods().Where(x => x.Name == "CreateAction");

    foreach (var method in methods)
    {
    if (method.GetGenericArguments().Length == methodInfo.GetParameters().Length - 1)
    {
    methodActual = method.MakeGenericMethod(methodInfo.GetParameters().Skip(1).Select(x => x.ParameterType).ToArray());
    }
    }
    }
    var actionToRegister = methodActual.Invoke(instance, new object[0]);

    关于C# 在注入(inject)第一个参数的给定方法上创建 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64383835/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com