使用反射调用重写后的基本方法如何使用反射调用派生类重写后的基本方法?ClassBase{公共虚拟voidFoo(){控制台。WriteLine("基地");}}classDerived:Base{publicoverridevoidFoo(){控制台。WriteLine("导出");}}publicstaticvoidMain(){Derivedd=newDerived();typeof(Base).GetMethod("Foo").Invoke(d,null);控制台.ReadLine();这段代码总是说“派生”......你不能那样做,即使使用反射。C#中的多态性实际上保证了Derived.Foo()将始终被调用,即使在Derived的实例返回到其基类时也是如此。从Derived实例调用Base.Foo()的唯一方法是显式地使其可从Derived类访问:}publicvoidBaseFoo(){base.Foo();}}尽管当前的答案已被接受,但实际上可以使用如下动态方法更改原始类:staticvoidMain(string[]args){Derivedfoo=newDerived();foo.Foo();MethodInfo方法=typeof(Base).GetMethod("Foo");DynamicMethoddm=newDynamicMethod("BaseFoo",null,newType[]{typeof(Derived)},typeof(Derived));ILGeneratorgen=dm.GetILGenerator();gen.Emit(OpCodes.Ldarg_1);gen.Emit(OpCodes.Call,方法);gen.Emit(OpCodes.Ret);varBaseFoo=(Action)dm.CreateDelegate(typeof(Action));BaseFoo(foo);控制台.ReadKey();可以看到还是比较简单的折腾了半天,终于找到了比DynamicMethod更好的方案:varmethod=typeof(object).GetMethod("ToString");varftn=method.MethodHandle.GetFunctionPointer();varfunc=(Func)Activator.CreateInstance(typeof(Func),obj,ftn);缺点sole.WriteLine(func());}}classOverride{publicoverridestringToString(){return"Nope";此解决方案为委托使用标准构造函数签名:publicDelegate(objecttarget,IntPtrftn)其中target是目标实例,ftn是函数指针,它使用基方法的函数指针直接调用它,因此委托将指向实际的基本方法,而不是重写的方法。这可以通过发布的代码来实现http://blogs.msdn.com/b/rmbyers/archive/2008/08/16/invoking-a-virtual-method-non-virtually.aspx反射允许您查看具有“Foo”方法也可以调用它。然而,这个方法是一个虚方法,这就是为什么你通过Derived类获得这个方法的实现,因为d就是这样(除了它还可以转换为Base)。没有[直接]方法可以从Derived对象调用Base的虚方法。正如FredericHamidi所展示的,Base类的方法可以通过Derived类(以不同的名称)公开,但它并不是真正调用Base的方法,而是调用Derived类的方法,而Derived类恰好调用了基地的方法。虽然这种方法让Derived类为Base类的方法提供一个“代理”,最终将执行您想要的操作,但这样做可能不是一个好主意:对象模型的设计可能存在缺陷:它会是一个相当奇怪的用例......你所看到的是设计的多态行为。重写虚方法时,调用重写类上的方法将从VMT调用后代类的实现。你的用例是什么,老实说这是一个设计问题。也许Kii正在寻找类似这样的东西classBase{publicvirtualvoidFoo(){Console.WriteLine("Base");}}classDerived:Base{//用new改变virtual//publicoverridevoidFoo(){Console.WriteLine("导出");}publicnewvoidFoo(){Console.WriteLine("Derived");}}staticvoidMain(string[]args){Derivedd=newDerived();d.Foo();//输出:派生的typeof(Base).GetMethod("Foo").Invoke(d,null);//输出:Base//或者你可以转换((Base)d).Foo();//输出:基础Console.ReadLine();}基数b=(基数)d;Console.WriteLine(b.GetType());//output:Derived1)Casting不能改变它的类类型。派生类:基础{公共覆盖voidFoo(){Console.WriteLine("Derived");}publicBasegetBase(){返回基数;//编译器无效}}2)以上是无效的,因为您正在创建派生对象实例化它时从未创建过Base对象的实例。您创建从Base类继承的Derived类的实例对象。希望,这就解释了为什么不能用派生对象调用基函数希望大家多多关注——本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
