【问题标题】:C# Create delegate of method where parameter types are unknown in runtimeC#在运行时创建参数类型未知的方法委托
【发布时间】:2014-10-31 08:38:33
【问题描述】:

我想要做的是以下(我一定不知道它是否可能);我知道运行时类型。我知道我想在运行时调用哪个方法。但是,我在编译时不知道这一点。

GetFunction 方法将无法创建给定 methodInfo 的委托,因为 inparam 不是对象类型。

有没有办法创建一个函数的委托,而我只知道我希望委托的方法的 Type 和 MethodInfo?

public sealed class Functions {
    public static int SetStrValue(string s) {
        // set a string
    }

    public static int SetIntValue(int i) {
        // set an int
    }
}

public sealed class GetFunctions {
    public Func<object, int> GetFunction(Type type, MethodInfo methodInfo) {
        // what I would like to do.
        Func<object, int> func = Delegate.CreateDelegate(typeof(Func<object, int>), methodInfo);
        return t => func(t);
    }
}

public class InvokeFunctions {
    public void invokeFunction() {
        Type t = typeof(String);
        MethodInfo methodInfo = typeof(Functions).GetMethod("SetStrValue");
        int i = GetFunctions.GetFunction(t, methodInfo).Invoke("hello");
    }
}

【问题讨论】:

  • 从问题本身的一个方面来说,为什么你们的课程是密封的?这通常不是一个好主意,因为它基本上是在说“我永远不想扩展这个类或以任何方式改变它”,而许多 .NET 类是密封的,这更有意义,因为 .NET 是框架。为什么你要求你的密封?

标签: c# types parameters delegates runtime


【解决方案1】:

您可以使用表达式树来创建委托。由于编译时类型未知,您可以尝试在运行时将参数转换为适当的类型。

public sealed class GetFunctions
{
    public static Func<object, int> GetFunction(MethodInfo methodInfo)
    {
        var obj = Expression.Parameter(typeof (object), "obj");
        var convert = Expression.Convert(obj, methodInfo.GetParameters().First().ParameterType);
        var call = Expression.Call(methodInfo, convert);
        var lambda = Expression.Lambda<Func<object, int>>(call, obj);

        return lambda.Compile();
    }
}

public class InvokeFunctions
{
    public void invokeFunction()
    {
        MethodInfo methodInfo = typeof(Functions).GetMethod("SetStrValue");
        int i = GetFunctions.GetFunction(methodInfo).Invoke("hello");

        MethodInfo methodInfo2 = typeof(Functions).GetMethod("SetIntValue");
        int i2 = GetFunctions.GetFunction(methodInfo2).Invoke(1);
    }
}

我已经删除了 Type 参数并直接从 Method 的第一个参数中获取它,如果这不是预期的行为,您可以更改它。

【讨论】:

    【解决方案2】:

    您可以使用泛型将其简化为:

    public sealed class Functions 
    {
        public static int SetValue<T>(T input) 
        {
            // set a value of type T
        }
    }
    

    然后调用函数:

    Functions.SetValue<string>("hello");
    

    如果您仍想使用委托,也可以使用通用委托定义:

    public delegate int MyDelegateFunction<T>(T input);
    

    【讨论】:

    • 这意味着我需要在编译时知道我要推断的类型。这里的主要问题是我正在使用一个针对不同类型具有不同功能的 API。我想在这里减少 if 语句。在这种情况下,我必须在 SetValue 函数中仍然检查类型并根据类型调用正确的函数。
    猜你喜欢
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多