Reputation: 31599
Is there a way to change the virtual methods tables in C#? like change where a virtual method is pointing?
class A
{
public virtual void B()
{
Console.WriteLine("B");
}
}
class Program
{
public static void MyB(A a)
{
Console.WriteLine("MyB");
}
public static void Main(string[] Args)
{
A a = new A();
// Do some reflection voodoo to change the virtual methods table here to make B point to MyB
a.B(); // Will print MyB
}
}
Upvotes: 4
Views: 2941
Reputation: 7342
You can make virtual B call a default delegate you choose. The following will allow inheritance and overriding: (actually overriding of already overriden :D)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class A
{
public delegate void delegateB();
public delegateB _B;
public A() {
_B = B;
}
public void Override(delegateB newB)
{
_B = newB;
}
public virtual void B()
{
if (_B != null && _B != this.B) {
Console.WriteLine("OVERRIDEN B IN A");
_B();
}
else {
Console.WriteLine("VIRTUAL B IN A");
}
}
}
class cB : A {
public override void B() {
if (base._B != null && base._B != this.B)
{
Console.WriteLine("OVERRIDEN B IN B");
_B();
}
else
{
Console.WriteLine("IN B");
}
}
}
class Program
{
class Overrider {
public void MyB()
{
Console.WriteLine("MyB");
}
}
public static void Main(string[] Args)
{
A a = new A();
a.B();
Overrider ovr = new Overrider();
a.Override(ovr.MyB);
a.B(); // Will print MyB
cB b = new cB();
b.B();
b.Override(ovr.MyB);
b.B();
}
}
}
Output:
VIRTUAL B IN A
OVERRIDEN B IN A
MyB
IN B
OVERRIDEN B IN B
MyB
You can even call base.B();
in cB.B() which will effectively call the overriden delegate but will give this output:
VIRTUAL B IN A
OVERRIDEN B IN A
MyB
IN B
OVERRIDEN B IN B
OVERRIDEN B IN A
MyB
I suggest you to take some similar approach or a design pattern approach and do not even think of reflection Emit. You code will be unusable in high performance applications. Delegates are fast, reflection is SLOW.
Upvotes: 1
Reputation: 13574
Dani,
What's your ACTUAL problem? Paint me a picture of where-abouts "breaking" an existing, tested class definition "on the fly" would be desirable. Forgive my scepticism... but I have plenty of scripting experience, so I'll take code that doesn't generate itself as it's running any day. I even (sort of) hate IOC for just that reason.
However, If you want to create an overriding (or implementing) class-definitions "on the fly" then I suppose you'd use byte-code-generation (atleast that's what you'd do in Java)... Here's a forum thread on that topic: http://bellyphant.com/2006/11/csharp_bytecode_generation
You could also generate source-code, and compiling it on the fly. Here's a cute free little utils class to compile C# on the fly: http://www.agilekiwi.com/on_the_fly.htm
Good luck with it anyway... It's an interesting question.
Cheers. Keith.
Upvotes: 1
Reputation: 25874
Take a look at LinFu.
On Linfu's author's Blog there's an example of using LinFu.AOP to intercept and change calls even to methods of classes that you don't control directly.
Upvotes: 4
Reputation: 391614
You cannot change the types with reflection, you can only reflect over the existing types.
You can, however, build new types using Reflection.Emit and related classes, but short of recompiling your assembly, a.B();
in your example will always call A.B()
.
Upvotes: 2