在执行期间修改C#类方法

时间:2009-04-13 20:23:08

标签: c# oop tdd

我想在不继承基类的情况下覆盖类方法,因为它需要花费大量的时间和修改,因此需要进行越来越多的测试。就像这样:

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

在代码的某处,我想做这样的事情:

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

这个changeMethod函数会覆盖TestClass的initialMethod,所以它会调用testMethod。

使用常规做法继承和覆盖方法不是一种选择,因为这个类A是一个图形组件,并且它(并且更改它)会破坏大量代码。

编辑:我们没有TestClass的基本代码,因此不能修改定义initialMethod作为委托的代码。

编辑2:由于这是一个图形组件,设计人员自动添加了大量代码。如果我要继承此代码,我将不得不替换设计器添加的所有代码。这就是为什么我不想替换这个组件。

6 个答案:

答案 0 :(得分:7)

您需要Strategy模式。

主要步骤:

  • 使用ie创建一个界面。 Do()签名
  • 您的 initialMethod()应调用 strategy.Do(),其中strategy是您的界面类型
  • 创建一个实现此接口的类。 Do()现在是你的测试方法。
  • 向您的主类注入此类的实例

如果工作不是那么大(让我们说只是颜色替换或其他什么)那么我同意Jhonny D. Cano用C#(匿名)代表的解决方案。

修改(编辑后2)

可能 - 就像概念验证一样 - 你应该继承该类并将所有从基类的引用替换为这个新类。这样做,没有别的。如果它有效,你可以考虑下一步(新方法或代表等)。

您只需要从版本控制系统中进行新的结帐,如果它可能失败,您可以放弃它。值得一试。

答案 1 :(得分:3)

也许你可以作为代表来做。

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

    initialMethod

    public TestClass() {
        myAction = initialMethod;
    }
}

然后在TestMethod

public testMethod()
{
    return;
}
test() {
    testClassInstance.myAction = testMethod;
}

答案 2 :(得分:2)

我认为你最好的选择是使用像LinFu这样的AOP框架。有一个代码项目文章解释它:

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

答案 3 :(得分:0)

如果'TestClass'是你定义的东西,你可以用属性和委托替换'initialMethod'定义,然后可以将其设置为具有给定签名的任何方法。 (即使是匿名的。)

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

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

以上代码未经测试。

答案 4 :(得分:0)

如果您没有使用扩展方法的代码。

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

在这里,您使用Closed for Modification Open for Extension。

这将为您没有源代码的库添加功能。这样做非常干净。

版:

在FrameWork 3.5中,有一些新的扩展方法。这些方法为封闭的程序集添加了功能,使您可以在功能中扩展已关闭的dll /程序集。

要使用它,例如你有一个你导入的dll,称为Graphics.dll(你的项目有参考)

首先,你要创建一个名为Extension的新静态类:

public static class Extensions
{
}

其次,您希望为名为Graphics.dll的{​​{1}}中包含的类添加额外的功能。你会这样做:

ChartGraph

第三,当你从public static class Extensions { public static void draw(this ChartGraph g) { // DO SOMETHING } } 实例化一个新对象时,你现在将拥有你创建的新方法:

graphics.dll

正如您所看到的那样,如果没有重新编译dll,您可以毫不费力地添加新功能,如果您没有源代码,那就很好。

答案 5 :(得分:0)

简短而简单的答案是:如果你不能调整基本的TestClass代码,不可以,你无法修改类来替换另一个方法。一旦我们开始做这样的事情,我们就会使用完全不同的语言,比如JavaScript。

答案越长:它取决于谁在调用替换方法。

如果是其他类,请查看是否无法在它们与不可修改的具体类之间实现Proxy。这是否可行取决于该类是实现接口,还是它自己的接口。

如果它是类本身,那么您唯一的选择是在设计时使用Reflector(或等效工具)或在运行时使用Reflection.Emit来反编译和修改类。然而,你必须非常伤害这条路线,因为它肯定是痛苦和脆弱的。

不幸的是,你仍然没有解释你正在尝试做什么以及为什么。在移动中替换方法是直接允许它的语言中的强大功能......可能有一些模拟库可以扭曲到足以完成反射的东西,但是你会在薄冰上滑冰。