C#OO设计问题与方法的覆盖

时间:2010-08-12 14:11:02

标签: c# design-patterns reflection oop override

情况:

Assembly 1
________________________             ________________________
| Class A               |           | Class B               |
|-----------------------|           |-----------------------|
| Method someMethod     |---------->| Method otherMethod    |
|                       |           |                       |
|_______________________|           |_______________________|

程序集1是其他开发人员可以使用的应用程序。 我们只给他们.dll所以如果我们不改变api,我们可以从应用程序发布更新。开发人员无法更改程序集1中的框架

方法是虚拟的,因此开发人员可以覆盖方法,以便在需要时实现自己的逻辑。

问题是开发人员无法覆盖B类中的otherMethod, 他可以覆盖它,但是A类总是从B类调用方法而不是覆盖方法。

Assembly 1
________________________             ________________________
| Class A               |           | Class B               |
|-----------------------|           |-----------------------|
| Method someMethod     |----XX---->| Method otherMethod    |
|                       |           |                       |
|_______________________|           |_______________________|
                \                                    |
                 \                                   |
                  \                                  |
Assembly 2         \                                 |
                    \                ________________|_______
                     \               | Class ExtendedB       |
                      \              |-----------------------|
                       \____________>| Method otherMethod    |
                                     |                       |
                                     |_______________________|

装配2具有对装配1的引用

部分类不起作用,因为它必须是相同的程序集,并且不能在2

上工作

这个问题有设计模式吗? 或者是否有其他解决方案或反射?

编辑添加了一个代码示例:

/* ASSEMBLY 1 */

namespace Assembly1
{
    public interface IAService
    {
        void TestMethod3();
        void TestMethod4();
    }

    public interface IBService
    {
        void TestMethod1();
        void TestMethod2();
    }

    public class AService : IAService
    {
        // Base implementation of AService
        public  virtual void TestMethod3()
        {
            //do something
        }
        public virtual void TestMethod4()
        {
            //do something
        }
    }

    public class BService : IBService
    {
        // Base implementation of BService
        public virtual void TestMethod1()
        {
            //do something
        }
        public virtual void TestMethod2()
        {
            //need to call AService implementation from assembly 2
        }
    }
}   





/* ASSEMBLY 2 */
namespace Assembly2
{
    public class NewAService : AService
    {
        public override void TestMethod3()
        {
            //default implementation which could be overridden
            base.TestMethod3();
        }

        public override void TestMethod4()
        {
            //default implementation which could be overridden
            //An implementation of IBService Should be called

            base.TestMethod4();
        }
    }
}

6 个答案:

答案 0 :(得分:4)

你应该重构

public interface IClassB
{
   void SomeMethod();
}
public Class A
{
    private IClassB myInstanceB = new ClassB();

    public ClassA(){}

    public ClassA(IClass B)
    {
      myInstanceB = B;
    }

    public void SomeMethod()
    {
        myInstanceB.SomeMethod();
    }
}

public ClassB : IClassB
{
   public void SomeMethod()
   {
      // some wicked code here...
   }
}

完成这个重构后,开发人员可以使用空构造函数来使用默认实现。如果他们需要一些其他逻辑而不是他们只需要实现接口IClassB并将其传递给另一个构造函数。

程序集2中的用法将是这样的

public class NewFunctionalityClass : IClassB
{
    public void SomeMethod()
    {
       //something else
    }
}
public TestClass()
{
   public void ShowMethod()
   {
      var defaultObject = new ClassA();
      defaultObject.SomeMethod();  // default implementation

     var otherObject = new ClassA(new NewFunctionalityClass());
     otherObject.SomeMethod(); // here the new implementation will run
   }
}

答案 1 :(得分:3)

假设A调用通过ExtendedB类型的变量引用的B实例,并且该方法在virtual中标记为Boverride中的ExtendedB,调用应该是多态的。它应该工作。也许你可以展示一些代码。

答案 2 :(得分:3)

在没有实际代码的情况下很难分辨,但是以面值来看你的图(顺便说一下,喜欢ASCII艺术!),我建议A类引用一个接口而不是硬编码到B级。

像这样:

// ----- this is in Assembly 1  -----------
public ClassA
{
    public MyInterface myDependentObject;
}

public interface MyInterface
{
    void OtherMethod();
}

public class ClassB : MyInterface
{
    public void OtherMethod()
    {
        // some code here...
    }
}


// ----- this is in Assembly 2  -----------
public class OtherB : MyInterface
{
    public void OtherMethod()
    {
        // some code here...
    }
}

在程序集2中,将OtherB分配给ClassA:

// ----- this is in Assembly 2  -----------
OtherB b = new OtherB();
ClassA a = new ClassA { myDependentObject = b };

现在,当ClassA执行myDependentObject.OtherMethod()时,它将从程序集2而不是程序集1定义中获取。

... HTH

答案 3 :(得分:1)

您能提供一些示例的缩减代码吗?我很欣赏ascii艺术,但我怀疑问题可能在于A如何获得它所使用的B。如果它实例化它自己的副本,则它无法在派生类中调用重写方法。

那就是说,我也同意其他人建议的界面重构是要走的路。允许A从接口IB工作,因此它必须使用提供的IB实现者,而不是生成自己的实现者。这样,提供的对象是B,B的子类还是其他完全无关紧要。它还使A,B和Bs子类更易于测试,这是一件好事。

答案 4 :(得分:0)

您可能需要使用策略或模板模式来解决此问题。

答案 5 :(得分:0)

有几种设计模式可行。这是我在阅读你的帖子时想到的列表(按此顺序)。

  1. ADAPTER
  2. DECORATOR
  3. TEMPLATE METHOD