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?

8 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.

Good Well said...

payroll software
Chemistry Online Tutor
Thank you for sharing
MM

Printer Setup Manual said...

donate for poor child
sponsor a child in need
volunteer in orphanage

Sherman Souto said...

Thank you for providing this blog really appreciate the efforts you have taken into curating this article if you want you can check out data science course in bangalore they have a lot to offer with regards to data science in terms of training and live projects.

Akshat said...

Great very helpful blog. Thanks For Sharing Such A Wonderful Blog. I will definitely go ahead and take advantage of this. Your Blog Is Very Informative. Again Thanks For Sharing This Blogs With Us. For more learning go through Skillslash.
For Data Science Course Data Science Course In Bangalore

neha jain said...

I am preparing for the most prestigious exam for my career and join the best mppsc coaching in indore for my preprarion must try.

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

Unknown said...

데이트홈케어 데이트홈케어 데이트홈케어

Post a Comment