Want to show your appreciation?
Please a cup of tea.

Friday, May 08, 2009

C#.Net Calling Grandparent's Virtual Method (base.base in C#)

Update: Open source project SharpCut delivers a less than 50K library which does what described here in one line plus much more. Check it out.

Calling parent's virtual method is easy, you can use base.VirtualMethod(). But C# has no support to call grandparent's virtual method. I guess everybody tried base.base.VirtualMethod() and that won't work.

I have searched the Google for how to call grandparents virtual method in C# learned that this isn't supported by VB.Net and C#. Only C++/CLI gives this power.

I need to do something very similar to the OnMouseDown example in this post. I can code in C++ but this is a class in a big C# project so this is no an option. The IL code in the C++ article reminded me that I should be able to use Reflection Emit to do the same.

    class A { public virtual string foo() { return "A"; } }

    class B : A { public override string foo() { return "B"; } }

    class C : B
    {
        private static readonly DynamicMethod baseBaseFoo;
        static C()
        {
            MethodInfo fooA = typeof(A).GetMethod("foo", BindingFlags.Public | BindingFlags.Instance);

            baseBaseFoo = new DynamicMethod(
                "foo_A",
                typeof(string),
                new Type[] { typeof(A) },
                typeof(A));
            ILGenerator il = baseBaseFoo.GetILGenerator();
            il.Emit(OpCodes.Ldarg, 0);
            il.EmitCall(OpCodes.Call, fooA, null);
            il.Emit(OpCodes.Ret);
        }
        public override string foo() { return (string)baseBaseFoo.Invoke(null, new object[]{this}); }
    }

It works, C.foo() returns "A". But this can obviously be improved in many ways. In next post, we'll try to

  • Create a utility method, or better extension method, that does all the IL generation.
  • Instead of _fooA.Invoke, we can probably use a delegate for type safety and performance.

So that we can write the code like this:

    class C : B
    {
        private static readonly Func<A, string> baseBaseFoo = 
            typeof(A).GetNonVirtualInvoker<Func<A, string>>("foo");
        public override string foo() { return baseBaseFoo(this); }
    }

Looks cool, isn't it?

3 comments:

Unknown said...

No one commented on this? In all of these years since the posting? This is a workable workaround when you have a closed library. Thanks for this. Cheers.

donardo jack said...

Kjøp Valium (Diazepam) 10mg i Norge

Kjøp oxycodone 30 mg i Norge

Köpa Ritalin 30mg i Sverige

Köp Concerta 54mg i Sverige

Köpa Adderall 30 mg i Sverige

link text
Kjøp Adderall 30 mg i Norge

Kjøp oxynorm 10 mg i Norge

link text

CEA Aviation said...

It’s clearly an exceptional and very useful fact. Thanks for sharing this helpful data with us. CEA Aviation is one of the Best DGCA Ground Classes in delhi. It gives admission to all of the aspirants seeking to start with Ground classes. You can enrol for Best Ground training for DGCA checks with us. Once you're clear with DGCA exam Counsellor Desk will assist you in choosing the best flight academy overseas.

Post a Comment