看《CLR via C#》中动态类型相关内容时,我想到了一个有意思任务:需要实现一个函数DynamicCallStaticMethod,包含四个参数:(dynamic a, dynamic b, Type t, string MethodName),目的是调用t对应的类型的静态成员函数MethodName,并将动态类型a与b作为这个静态成员函数的参数。
例如,假设我定义了某个类型SomeClass,其中包含静态成员函数“Concat",那么我希望在DynamicCallStaticMeghod中调用SomeClass.Concat(a, b)。其中a与b是dynamic的,在运行程序时根据实际类型class1与class2调用SomeClass.Concat对应的重载版本SomeClass.Concat(class1, class2)。当然,如果没有这种重载函数就会运行出错了。
听起来是不是有点蛋疼哈哈哈哈哈哈哈,来吧,给出我的代码:
static object DynamicCallStaticMethod(dynamic a, dynamic b, Type t, string MethodName)
{ //对动态参数的a与b调用t类型的名为MethodName的静态方法
//例如,t为typeof(SomeClass),则相当与SomeClass.MethodName(a, b)
//运行时动态获取a与b的实际类型,然后调用相应的SomeClass.MethodName重载
Type[] argTypes = new Type[] { a.GetType(), b.GetType() };
MethodInfo method = t.GetMethod(MethodName, argTypes);
object[] arguments = new object[] { a, b };
object result = method.Invoke(null, arguments);
return result;
}
我只是看书的过程中突然想到这么个东西,简单的实现了程序,上面这段代码存在一些安全问题。比如如果SomeClass.Concat(class1, class2)的返回类型如果是void那么运行时会报错。
如果想要更完善的版本,大家可以参考一下CLR via C#第五章末尾那个程序。
下面对上面的函数进行测试。
首先定义一个类
class FunnyClass
{
public static object Concat(FunnyClass f1, string s1)
{
return "FunnyClass.Concat(FunnyClass, String)";
}
public static object Concat(FunnyClass f1, FunnyClass f2)
{
return "FunnyClass.Concat(FunnyClass, FunnyClass)";
}
}
下面是一个测试函数:
static void testDynamicCall()
{
Console.WriteLine("## test the function 'static object DynamicCallStaticMethod(dynamic a, dynamic b, Type t, string MethodName)'");
String a = "xxx", b = "yyyy";
object a_b = DynamicCallStaticMethod(a, b, typeof(String), "Concat");
Console.WriteLine((string)a_b);
FunnyClass f1 = new FunnyClass();
object f1_a = DynamicCallStaticMethod(f1, a, typeof(FunnyClass), "Concat");
Console.WriteLine((string)f1_a);
object f1_f1 = DynamicCallStaticMethod(f1, f1, typeof(FunnyClass), "Concat");
Console.WriteLine((string)f1_f1);
f1_a = DynamicCallStaticMethod(f1, a, f1.GetType(), "Concat"); #尤其注意这个调用,DynamicCallStaticMethod的第三个参数也根据动态类型对象在运行时才能得知
Console.WriteLine((string)f1_a);
Console.WriteLine("## end");
}
看看运行结果:
可以看到,第一次调用DynamicCallStaticMethod时,其内部调用的是String的静态成员Concat。后三次DynamicCallStaticMethod调用的内部则是使用了自定义类型FunnyClass的静态成员Concat的不同重载形式。
实际用途么…暂时我也想不到,不知道可不可以作为c#的面试题。如果有面试官采用或较为直接的借鉴了本文内容,请私信博主支付稿酬。
以上内容纯属博主图一乐,但如果有错误之处,或是更好的实现方法,欢迎大家私信我。如果有朋友提出了我认为有价值的意见,那么我将分你一部分本文稿酬(如果有的话)。