public class A
{
...
public virtual void PrintMe() { /* do A */ }
}
public class B : A
{
...
public override void PrintMe() { /* do B *开发者_运维技巧/ }
}
public class C : B
{
...
public override void PrintMe() { /* do C */ }
private void Fun()
{
// call C::PrintMe - part one
PrintMe();
// call B::PrintMe - part two
base.PrintMe();
// call A::PrintMe - part three
???
}
}
Is the code of part two correct?
How to call
A::PrintMe
insideC::Fun
?
Your question 1 will work as expected, it will do B.PrintMe()
Your question 2 is not quite so simple. There is no implicit or explicit way to execute A.PrintMe()
.
The only way I can think to achieve your goal is with the addition of a protected method on A
which can be called from C
.
public class A
{
protected void BasePrintMe() { Console.WriteLine("A"); }
public virtual void PrintMe() { BasePrintMe(); }
}
public class B : A { public override void PrintMe() { Console.WriteLine("B"); } }
public class C : B
{
public override void PrintMe() { Console.WriteLine("C"); }
public void FunA()
{
// call C::PrintMe - part one
PrintMe();
// call B::PrintMe - part two
base.PrintMe();
// call A
this.BasePrintMe();
}
}
output:
C
B
A
If you want this desired functionality, you can call base.PrintMe()
in your B
class.
public class B : A
{
public override void PrintMe()
{
/* do B */
base.PrintMe();
}
}
Otherwise, you can't call the implementation from class A
without resorting to something hackish.
You could add a method to each class that would do a base.PrintMe()
. In A, this method would do nothing as it has no base class.
public class A
{
public virtual void PrintMe()
{
Debug.WriteLine( "PrintMe: A" );
}
public virtual void PrintMyBase()
{
}
}
public class B : A
{
public override void PrintMe()
{
Debug.WriteLine( "PrintMe: B" );
}
public override void PrintMyBase()
{
base.PrintMe();
}
}
public class C : B
{
public override void PrintMe()
{
Debug.WriteLine( "PrintMe: C" );
}
public override void PrintMyBase()
{
base.PrintMe();
}
private void Fun()
{
// call C::PrintMe - part one
PrintMe();
// call B::PrintMe - part two
PrintMyBase();
// call A::PrintMe - part three
base.PrintMyBase();
}
}
The befit here is that no class has to know anything more than it's base class and we can control what's exposed down the inheritance chain.
Hope this helps
There's no language-supported way of doing this, which is a handy hint to suggest that you shouldn't do it.
If you find yourself needing this in real-world code then you should really try to re-think your design.
Anyway, to answer the question, you can do this using reflection and some custom IL-generation, like so:
private void Fun()
{
// call C::PrintMe - part one
PrintMe();
// call B::PrintMe - part two
base.PrintMe();
// call A::PrintMe - part three
MethodInfo mi = this.GetType().GetMethod("PrintMe").GetBaseDefinition();
var dm = new DynamicMethod("dm", null, new[] { typeof(object) }, this.GetType());
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, mi); // use call rather than callvirt
il.Emit(OpCodes.Ret);
var action = (Action<object>)dm.CreateDelegate(typeof(Action<object>));
action(this);
}
精彩评论