2014-10-31 50 views
0

我想要做的是以下(我不知道它是否可能);我知道一个运行时间类型。我知道我想在运行时调用哪种方法。但是,我不知道这在编译时间。C#在运行时创建参数类型未知的方法代理

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

有没有办法创建一个函数的委托,我只知道我希望委托的方法的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"); 
    } 
} 
+0

问题本身的一面为什么你的课程是封闭的?这通常不是一个好主意,因为它基本上说'我永远不想扩展这个类或以任何方式改变它',而许多.NET类是封闭的,因为.NET是框架,所以这样做更有意义。你为什么要求你的密封? – sydan 2014-10-31 08:51:13

回答

3

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

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参数,并直接从方法的第一个参数采取它,如果这不是你可以改变它的预期的行为。

+0

谢谢!有用。 :) – Ekenstein 2014-10-31 10:31:24

0

可以使用泛型来简化这只是:

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); 
+0

这意味着我需要在编译时知道我推断的类型。 这里的主要问题是,我正在使用一个具有不同类型功能的API。 我想在这里减少if语句。 在这种情况下,我必须在SetValue函数中检查类型并根据类型调用正确的函数。 – Ekenstein 2014-10-31 08:55:42