C#方法中的反射方式和委托方式(小实例)

在开发过程中对静态方法的调用是通过类型名后面加个点而后是调用方法的名称,对类型实例方法的调用是通过new一个对象,而后点加方法名称,这是最熟悉不过的两种方式。还可以通过读取CLR元数据,利用反射进行方法调用。在利用反射方式调用方法时,最重要的两个类是System.Type和System.Reflection.MethodInfo。用MethodInfo类型的Invoke方法调用方法,必须传入目标对象实例的引用。如下:

 public class Calculate
{
private int Add(int leftNum, int rightNum)
{
return leftNum + rightNum;
}
protected string Hello(string name)
{
return "你好:" + name;
}
}

委托方式

任何对象都可以调用委托,只要方法返回值以及方法签名和委托声明一样就行。

  public delegate int DelegateCaculate(int a,int b);
public class Calculatetest
{
public int Add(int num1, int num2)
{
return num1+num2;
}
public static int Subtract(int num1,int num2)
{
return num2 - num1;
}
}

控制台调用:

class Program
{
static void Main(string[] args)
{
//用type.getmethod的方法获取类型方法,BindingFlags设置查找方法的范围
//本列是公有方法,私有方法而且是非静态的才被查找,如果要查找静态方法
//需要设置BindingFlags.Static
System.Reflection.MethodInfo method = typeof(Calculate).GetMethod("Add", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (method == null)
return;
//调用方法的参数
object[] paras = { 10, 20 };
//目标对象实例:new Calculate()
object result = method.Invoke(new Calculate(), paras);
Console.WriteLine(result);
System.Reflection.MethodInfo mt = typeof(Calculate).GetMethod("Hello", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (mt == null)
return;
//调用方法的参数
object[] para = { "李光辉" };
object rs = mt.Invoke(new Calculate(), para);
Console.WriteLine(rs);
Console.ReadLine();

//委托的调用
DelegateCaculate add = new DelegateCaculate(new Calculatetest().Add);
DelegateCaculate subtract = new DelegateCaculate(Calculatetest.Subtract);
Console.WriteLine("add:" + add(10, 20));
Console.WriteLine("subtract:" + subtract(10, 20));
Console.ReadLine();
}
}

委托与接口

接口与委托都拥有调用特定方法的能力,所以他们在这点很相像。但是接口需要目标方法的类型声明必须与该接口兼容,而委托可以被任何类型调用,只要该类型的目标方法签名和委托签名匹配即可。

那么何时用委托,何时用接口呢,msdn 总结的非常好,我就直接给粘贴过来了,

委托在以下情况很有用:

1、 调用单个方法。

2、 一个类希望有方法规范的多个实现。

3、 希望允许静态方法实现规范。

4、 希望类似事件的设计模式。

5、 调用方不需要知道或获得实现与委托签名匹配的方法的对象。

6、 实现的提供程序希望只对少数选择组件“分发”规范实现。

7、 需要方法的组合。

接口在以下情况很有用:

1、 规范定义一组相关方法。

2、 类通常只实现规范一次。

3、 接口的调用方希望转换为接口类型或从接口类型转换,以获得其他接口或类。

 1 private void callObjectEvent(Object obj, string EventName)  
2 {
3 //建立一个类型,AssemblyQualifiedName拿出有效的名字
4 Type t = Type.GetType(obj.GetType().AssemblyQualifiedName);
5 //参数对象
6 object[] p = new object[1];
7 //产生方法
8 MethodInfo m = t.GetMethod(EventName, BindingFlags.NonPublic | BindingFlags.Instance);
9 //参数赋值。传入函数
10 //获得参数资料
11 ParameterInfo[] para = m.GetParameters();
12 //根据参数的名字,拿参数的空值。
13 p[0] = Type.GetType(para[0].ParameterType.BaseType.FullName).GetProperty("Empty");
14 //调用
15 m.Invoke(obj, p);
16 return;
17 }
18
19 //调用例子。
20 //调用Button1的onclick
21 callObjectEvent(Button1,"OnClick");
22
23 //调用Button5的OnKeyPress
24 callObjectEvent(Button5,"OnKeyPress");
25
26 //调用Text1的OnTextChanged
27 callObjectEvent(Text1, "OnTextChanged");
private void callObjectEvent(Object obj, string EventName, EventArgs e=null)  
{
//建立一个类型
//Type t = typeof(obj.GetType);
Type t = Type.GetType(obj.GetType().AssemblyQualifiedName);
//产生方法
MethodInfo m = t.GetMethod(EventName, BindingFlags.NonPublic | BindingFlags.Instance);
//参数赋值。传入函数
//获得参数资料
ParameterInfo[] para = m.GetParameters();
//根据参数的名字,拿参数的空值。
//参数对象
object[] p = new object[1];
if (e == null)
p[0] = Type.GetType(para[0].ParameterType.BaseType.FullName).GetProperty("Empty");
else
p[0] = e;
//调用
m.Invoke(obj, p);
return;
}

//调用例子。
//调用Button1的onclick
callObjectEvent(Button1,"OnClick");
//调用Button5的OnKeyPress
callObjectEvent(Button5,"OnKeyPress");
//调用Text1的OnTextChanged
callObjectEvent(Text1, "OnTextChanged");
//调用Form的KeyPress事件, this就是那个winform, 并且传入回车键
callObjectEvent(this, "OnKeyPress", new KeyPressEventArgs((char)13));







你可能感兴趣的:(C#)