【问题标题】:How can I "override" a method in a partial class?如何“覆盖”部分类中的方法?
【发布时间】:2013-09-24 05:12:48
【问题描述】:

我一直在寻找解决我们公司遇到的复杂问题的方法。该公司是覆盖我国四个“地区”的四家公司联盟的一部分。 我们的分支用 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 类并在您自己的区域类中覆盖它。

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

【问题讨论】:

  • 结果应该选择哪种方法?
  • if(myCompany){MyCompanyMethod();} else {OtherMethod();}
  • 看起来你正在通过使用部分类使问题变得更复杂。恕我直言,使用良好的“对象组合/继承”将是可行的方法。
  • @Extra:现在您已经亲身体验了为什么static 容易导致开发死胡同。如果该方法是virtual(和/或接口的一部分),那么用更专业的类的实例替换调用它的实例将是一个“简单”的事情(您不需要重写每个称呼)。把课带回家。

标签: c#


【解决方案1】:

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

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

        }
#endif

    }


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

        }
#endif
    }

在项目属性中,Build->条件编译符号:根据需求区域添加Regional或National。

【讨论】:

  • 编译标签很脆弱,当有现有模式可用于使用标准语言功能解决问题时,这不是一种有用的方法。
【解决方案2】:

就像 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 容器,您甚至可以将策略连接到配置文件中。

编辑

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

【讨论】:

    【解决方案3】:

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

    1. 静态方法不能是虚拟的。
    2. 您应该封装变化的内容。这意味着公司特定的代码至少应该在一个单独的类中(最好是一个单独的程序集)。您将需要提供带有您公司特定代码的基本程序集。您可以将 strategy pattern 与 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");
        }
    }
    

    【讨论】:

    • 是的。基本上这件事应该通过组合和配置来解决,而不是通过部分或继承来解决。
    【解决方案4】:

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

    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.
         }
    }
    

    看到问题了吗?

    【讨论】:

      猜你喜欢
      • 2012-04-12
      • 2013-06-18
      • 2016-02-23
      • 2018-01-14
      • 2012-08-02
      • 1970-01-01
      • 2020-10-05
      • 1970-01-01
      • 2015-03-29
      相关资源
      最近更新 更多