在子类的override方法中调用父类的父类的未被重写的方法
今天做一个自定义控件,扩展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方法