今天做一个自定义控件,扩展TableLayoutPanel这个控件加一些自己的属性,重写OnPaintBackground这个虚方法,
控件的继承关系是这样的:
Control
ScrollableControl
Panel
TableLayoutPanel
这个虚方法在Control类中被定义,在ScrollableControl中被重写,在TableLayoutPanel中被又一次重写,
我自己的控件继承了TableLayoutPanel控件,因为TableLayoutPanel对OnPaintBackground方法重写时会进行对表格边框绘画,
而我仅仅需要给我画出背景,不需要边框,那么自然而然的想到下面的代码:
1 public class BaseClass
2 {
3 protected int i { get; set; }
4
5 protected virtual string GetString()
6 {
7 i = 1;
8 return "BaseClass";
9 }
10 }
11
12 public class SubClass : BaseClass
13 {
14 protected override string GetString()
15 {
16 //return base.GetString();
17 base.i = 2;
18 return "SubClass";
19 }
20 }
21
22 public class SubSubClass : SubClass
23 {
24 protected override string GetString()
25 {
26
27 //want to call base.base.GetString
28 base.i = 3;
29 return "SubSubClass";
30 }
31 }
32
33 public class MyClass : SubSubClass
34 {
35 protected override string GetString()
36 {
37
38 MethodInfo miOnPaintBackground = typeof(SubClass).GetMethod(
39 "GetString",
40 BindingFlags.Instance | BindingFlags.NonPublic,
41 Type.DefaultBinder,
42 new Type[] { },
43 null);
44
45
46 object o = miOnPaintBackground.Invoke(this as SubClass, null);
47
48 return (string)o;
49 }
50
51 public string CallMethod()
52 {
53 return this.GetString();
54 }
55 }
56
57 public class Program2
58 {
59 [STAThread]
60 static void Main()
61 {
62 MyClass m = new MyClass();
63
64 string s = m.CallMethod();
65
66 Console.WriteLine(s);
67
68 }
69 }
很不幸,溢出了,是死循环,反射回来的并不是基类的基类的方法,而是我MyClass里面重写的方法。有请google大神出场,得到两篇文章:
http://stackoverflow.com/questions/4357729/use-reflection-to-invoke-an-overridden-base-method
http://blogs.msdn.com/b/rmbyers/archive/2008/08/16/invoking-a-virtual-method-non-virtually.aspx
我们改造下我自己的类:
1 public class MyClass : SubSubClass
2 {
3 protected override string GetString()
4 {
5
6 MethodInfo miOnPaintBackground = typeof(SubClass).GetMethod(
7 "GetString",
8 BindingFlags.Instance | BindingFlags.NonPublic,
9 Type.DefaultBinder,
10 new Type[] { },
11 null);
12
13
14
15 var ftn = miOnPaintBackground.MethodHandle.GetFunctionPointer();
16 var func = (Func<string>)Activator.CreateInstance(typeof(Func<string>), this as SubClass, ftn);
17 string s = func();
18
19 //object o = miOnPaintBackground.Invoke(this as SubClass, null);
20
21 return s;
22 }
23
24 public string CallMethod()
25 {
26 return this.GetString();
27 }
28 }
ok,得到我们先要的结果SubClass,越过了基类的重写,执行了基类的基类的protected override方法