4

我一直在寻找解决我们公司遇到的复杂问题的方法。该公司是覆盖我国四个“地区”的四家公司联盟的一部分。我们的分支用 C# 开发了一个 WebService,我们将这个项目分发给其他分支的开发人员。每个人都在自己的服务器中托管 WebService。

现在,当公司相处不融洽时,我一直在为一些你可以期待的事情而苦苦挣扎。我必须调整现有方法以适应我们的“区域需求”。

所以我有这门课:

public partial class MyClass{
     public static ComplexReturnType MyMethod(){
          // National code. Everyone uses this block of code.
     }
}

我创建了一个区域文件夹,在将 DLL 分发到其他分支时,我将从编译中排除该文件夹。在这个文件夹中,我创建了文件 MyClass.cs 并继续:

public partial class MyClass{
     public static ComplexReturnType MyMethod(){
          // Regional code. Only my commpany will use this.
     }
}

该方法MyMethod在其他文件中调用。我了解它partial的工作原理,但是如果不创建子类并重写其他文件中已经存在的每个调用,我就找不到适合我需求的解决方案。

有谁知道如何处理这个问题?

回答后编辑

我决定采用策略设计模式,完成后我想“如果一个分支决定覆盖任何方法,所有其他分支都必须在其区域策略类中使用国家代码覆盖相同的方法”。

所以这不是很好。相反,我这样做了:

public class VStrategy
{
    public virtual ComplexReturnType MyMethod(){
        // National code. Method moved from MyClass
    }
    public virtual AnotherReturnType MySecondMethod(){
        // National code. Method moved from MyClass
    }
}

public class SomeBranchStrategy: VStrategy
{
    public override ComplexReturnType MyMethod() {
        // Regional code for overriding a method
    }
}

public class AnotherBranchStrategy: VStrategy
{
    public override AnotherReturnType MySecondMethod(){ {
        // Regional code for overriding a method
    }
}

public class MyClass
{
    private static VStrategy _strategy = new VStrategy();
    public static VSTrategy Strategy { get {...}; set {...} }
    public static ComplexReturnType MyMethod()
    {
        return Strategy.MyMethod();
    }
    public static ComplexReturnType MySecondMethod()
    {
        return Strategy.MySecondMethod();
    }
}

这样,在没有接口的情况下,每个分支都可以覆盖他们想要的任何方法,而不会影响其他分支。您只需将方法代码移动到 VStrategy 类并在您自己的区域类中覆盖它。

希望这可以帮助任何可能处于这种情况的人。

4

4 回答 4

8

就像 Maurice Stam 所说,封装变化的东西。乍一看,我会使用策略模式: http ://www.oodesign.com/strategy-pattern.html

public interface IStrategy
{
    ComplexReturnType MyMethod();
}

public class NationalDefaultStrategy : IStrategy
{
    public ComplexReturnType MyMethod() { }
}

public class BostonStrategy: IStrategy
{
    public ComplexReturnType MyMethod() { }
}

public class MyClass
{
    private static IStrategy _strategy = new NationalDefaultStrategy();
    public static ISTrategy Strategy { get {...}; set {...} }
    public static ComplexReturnType MyMethod()
    {
        return _strategy.MyMethod();
    }
}

这样,您可以轻松更改运行时使用的策略

MyClass.Strategy = new BostonStrategy();

如果您将其设置为实例方法而不是静态方法(我可能会)并决定使用像 Castle Windsor 这样的 IoC 容器,您甚至可以将策略连接到配置文件中。

编辑

从逻辑上讲,每个分支都有自己的配置文件。使用这种方法有两个优点:

  • 所有分支都将使用相同的代码库
  • 您的代码将遵守 Open Closed 原则,该原则指出您的类应该关闭以进行修改,并打开以进行扩展:http ://en.wikipedia.org/wiki/Open/closed_principle 。
于 2013-09-19T08:24:39.650 回答
2

您当前的方法存在一些问题。

  1. 静态方法不能是虚拟的。
  2. 您应该封装变化的内容。这意味着公司特定的代码至少应该在一个单独的类中(最好是一个单独的程序集)。您需要提供带有您公司特定代码的基本程序集。您可以将此策略模式与 IoC / Dependency Injection结合使用。
  3. 将包含代码的基本方法设为虚拟的一个风险是重复使用的代码将被复制。对此的解决方案是创建一个包含通用代码的密封方法,该方法使用公司的抽象(或空虚拟)方法,这些方法将从密封方法中调用。结合我之前的观点,这意味着调用已在注入实例上实现的方法。
  4. 如果问题仅限于本地化,您应该使用 .NET 提供的解决方案(即卫星程序集),其中包含特定于文化的资源。但是,您将同一个国家/地区划分为 4 个区域,因此我假设您具有特定于区域的逻辑而不是本地化问题。

实现上述建议的示例代码:

public class SharedClass
{
    private readonly IRegionCode m_RegionLogic;

    // Constructor with dependency injection
    public SharedClass(IRegionCode mRegionLogic)
    {
        this.m_RegionLogic = mRegionLogic;
    }

    // Method called by the webservice
    public void YourMethod()
    {
        // reused base logic here
        Trace.Write("Somehting");

        // Invoke region specific code
        m_RegionLogic.Foo();

        // reused base logic here
        Trace.Write("Somehting");
    }
}

// Contract for regions to implement
public interface IRegionCode
{
    void Foo();
}

// Example of an injected class
public class FirstRegionCode : IRegionCode
{
    public void Foo()
    {
        Trace.Write("Bar");
    }
}
于 2013-09-19T08:18:54.073 回答
1

您需要使用编译标签来避免例如:

public partial class MyClass
    {
#if National
        public static void NationalMethod()
        {

        }
#endif

    }


    public partial class MyClass
    {
#if Regional
        public static void NationalMethod()
        {

        }
#endif
    }

在项目属性中,构建->条件编译符号:根据需要的区域添加区域或国家。

于 2013-09-19T08:45:08.440 回答
1

我认为您误解了部分课程的用途!创建一个分部类仅仅意味着类的源代码被分割成单独的文件。将所有源代码写入同一个文件没有区别,所以基本上你写的是:

public class MyClass{
     public static ComplexReturnType MyMethod(){
          // National code. Everyone uses this block of code.
     }

     public static ComplexReturnType MyMethod(){
          // Regional code. Only my commpany will use this.
     }
}

看到问题了吗?

于 2013-09-19T08:22:32.700 回答