How to invoke (non virtually) the original implementation of a virtual method?

后端 未结 4 1129
伪装坚强ぢ
伪装坚强ぢ 2020-12-18 01:20

I have the following situation:

In a 3rd party library (can not be modified):

class A { public virtual void M() {} }

class B : A { public override v         


        
相关标签:
4条回答
  • 2020-12-18 01:27

    You cannot do that. You should probably design your class hierarchy differently, because it looks strange that C inherits from B, while behaving like A.

    Anyway, it could make sense in your case. Then you should make another method in A which you will not override:

    class A {
        protected virtual void basicM() {}
        public virtual void M() { basicM(); }
    }
    class C {
        public override void M() { basicM(); }
    }
    

    BTW, if you name the method as I did in the example, then you should probably rethink the whole thing. If this hierarchy is justified, than basicM probably performs something that deserves to be a separate method with a different name, perhaps even a public method.

    0 讨论(0)
  • 2020-12-18 01:34

    you can generate dynamic method to make proxy that use Call (not CallVirt) instruction

            var x = new C();
            var m = typeof (A).GetMethod("M");
            var dm = new DynamicMethod("proxy",  typeof (void), new [] {typeof(C)}, typeof (C));
            var il = dm.GetILGenerator();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Call, m);
            il.Emit(OpCodes.Ret);
            var action = (Action<C>)dm.CreateDelegate(typeof (Action<C>));
            action(x);
    
    0 讨论(0)
  • 2020-12-18 01:43

    In my previous answer I missed the fact that A and B are in an external library and cannot be modified. In that case, I would suggest a different approach. Basically, if the design flaw is in B, you can’t use B. Subclass from A instead.

    The unfortunate consequence of this, of course, is that you may need to reimplement some or all of the functionality in B. You may be able to copy the code from Reflector if necessary. I realise that this sounds undesirable, but I still think it is preferable to using unmodifiable code that has a known issue that causes you problems.

    0 讨论(0)
  • 2020-12-18 01:44

    I’m afraid this is not possible directly the way you describe — the purpose of virtual methods is for the overriding to be transparent. So the only way to do this at all is via a workaround.

    Let me try to whip one up, but please be aware that this is a hacky suggestion. If you really need this construct in your code, it may be an indication that your code has a fundamental design flaw somewhere else, so restructuring something might be more desirable than filling it with yet another design flaw. But anyway, here goes...

    class A {
        public virtual void M() { m_protected(); }
        protected void m_protected() { /* code goes here */ }
    }
    
    class B {
        public override void M() { /* code here, possibly invoking base.M() */ }
    }
    
    class C {
        public override void M() { m_protected(); }
    }
    
    0 讨论(0)
提交回复
热议问题