tags:

views:

708

answers:

6

I'd like to override a class method without inheriting the base class because it'd take a lot of time and modifications and, therefore, more and more tests. It's like this:

class TestClass{
    public void initialMethod(){
        ...
    }
}

And somewhere on the code, I'd like to do something like this:

public testMethod()
{
    return;
}
test(){
    changeMethod(TestClass.initialMethod, testMethod);
}

And this changeMethod function would override the TestClass initialMethod so that it'd call testMethod instead.

Inheriting and overriding the method using normal practices is not an option, as this class A is a graphic component and, inhereting it (and changing it) would break lots of code.

Edit: We don't have the base code for the TestClass, so it's not an option to modify the code there defining the initialMethod as a delegate.

Edit 2: Since this is a graphical component, the designer added a lot of code automatically. If I were to inherit this code, I would have to replace all code added by the designer. That's why I wouldn't like to replace this component.

+6  A: 

You need the Strategy pattern.

Main steps:

  • Create an interface with ie. Do() signature
  • Your initialMethod() should call a strategy.Do(), where strategy is type of your interface
  • Create a class that implements this interface. Do() is your testmethod now.
  • Inject into your main class an instance of this class

If the job it's not so big (let's say just a color replacement or something) then I agree with Jhonny D. Cano's solution with C# (anonymous)delegates.

Edit (after edit 2)

May - just as proof-of-concept - you should inherit the class and replace all references from base class to this new. Do this, and nothing else. If it works, you can think about the next steps (new methods or delegates etc.)

You need only a new checkout from your version control system, and if it maybe fails you can abandon it. It's worth trying.

boj
The Strategy pattern is well and good in itself, but doesn't help if the base class code can't be modified.
Pontus Gagge
Oh yes, I see "edit 2".
boj
A: 

If 'TestClass' is something you defined, you could replace the 'initialMethod' definition with a property and delegate which can then be set to any method with a given signature. (Even anonymous ones.)

class TestClass {
  Action _myMethod;
  Action MyMethod {
    get { return _myMethod; }
    set { _myMethod = value; }
}

var tc = new TestClass()
tc.MyMethod = () -> Console.WriteLine("Hello World!");
tc.MyMethod()

The above code is untested.

YotaXP
+2  A: 

Perhaps you can do it as a delegate.

class TestClass {
    public Action myAction;
    public void initialMethod(){
        ...
    }

    initialMethod

    public TestClass() {
     myAction = initialMethod;
    }
}

and then on TestMethod

public testMethod()
{
    return;
}
test() {
    testClassInstance.myAction = testMethod;
}
Jhonny D. Cano -Leftware-
A: 

If you dont have the code use Extension Methods.

public void doSmth(this objectYOUWANT arg) { //Do Something }

Here you use the principle Closed for Modification Open for Extension.

This will add functionality to the library you dont have the source code. Its very clean to do it this way.

Best Regards!

Edition:

In FrameWork 3.5 there is something new called Extension Methods. These kind of methods adds functionality to a closed Assembly letting you Extend in functionality a closed dll/assembly.

To use this for example you have a dll that you import, that is called Graphics.dll (you have the reference on your project)

First of all you shoud create a new static class called for example Extension:

  public static class Extensions
    {
    }

Second, you want to add extra functionality to a class contained in Graphics.dll named ChartGraph. You will do this:

    public static class Extensions
    {
        public static void draw(this ChartGraph g)
        {
           // DO SOMETHING
        }
    }

Third, when you instantiate a new object from the graphics.dll you now will have the new method you have created:

  ChartGraph myG = new ChartGraph();
  myG.draw();

As you can see there you have added new functionality without much effort without recompiling the dll, this is good if you dont have the source code.

hope this helps!

MRFerocius
Where would I add this code? Could you clarify it a little bit more?
Rodrigo
that will only add a new method, not override the implementation of the existing method.
Erich Mirabal
He doesnt want to override the method Erich... read his question.Best Regards!
MRFerocius
A: 

The short and simple answer is: if you can't adjust the base TestClass code, no, there's no way you can modify the class to replace a method by another. Once we started doing stuff like that, we'd be in a completely different kind of language, like JavaScript.

The longer answer is: it depends on who is calling the replaced method.

If it's other classes, see if you can't implement a Proxy in between them and the unmodifiable concrete class. Whether this is doable depends on whether that class implements interfaces, or is its own interface.

If it's the class itself, then your only option is to decompile and modify the class, at design time using Reflector (or equivalent tools), or at runtime using Reflection.Emit. However, you'd have to be hurting pretty badly to go this route, as it's sure to be painful and brittle.

Unfortunately you still haven't explained what you are trying do and why. Replacing methods on the go is powerful stuff in the languages that permit it directly... There might be mocking libraries that can be twisted sufficiently far to do the reflection stuff, but then you'd be skating on thin ice.

Pontus Gagge
+2  A: 

I think your best bet might be to use a AOP framework like LinFu. There's a codeproject article explaining it:

Introducing LinFu, Part VI: LinFu.AOP – Pervasive Method Interception and Replacement for Sealed Types in Any .NET Language

Pop Catalin
I would only recommend AOP as a last resort in this case. If you can contact the vendors of your TestClass and arrange to add a hook for your target method (or fix it, because I suspect you're trying to avoid undesirable behavior), by all means prefer this to AOP.
Anton Tykhyy