C# 将公共方法转换为扩展方法

C# 将公共方法转换为扩展方法,c#,extension-methods,public-method,C#,Extension Methods,Public Method,在我的项目的核心库中,我们有一个非常大的类,它正趋向于成为一个。其中一个原因是,在一段时间内,本应在不同模块中的任务已被放入该类。前- class HugeClass{ public void DoModuleXJob(){} public void DoModuleYJob(){} } 重构并将不需要的、特定于模块的行为移出这个类的过程中的一个问题是,模块X和模块Y要修改它们的代码需要做大量的工作。 作为一项工作,我考虑将这些方法转换为扩展方法,然后将它们转移到相关模块。例如

在我的项目的核心库中,我们有一个非常大的类,它正趋向于成为一个。其中一个原因是,在一段时间内,本应在不同模块中的任务已被放入该类。前-

class HugeClass{
    public void DoModuleXJob(){}
    public void DoModuleYJob(){}
}
重构并将不需要的、特定于模块的行为移出这个类的过程中的一个问题是,模块X和模块Y要修改它们的代码需要做大量的工作。 作为一项工作,我考虑将这些方法转换为扩展方法,然后将它们转移到相关模块。例如—

// in module X
static class HugeClassExtensions{
    public static void DoModuleXJob(this HugeClass instance){}
} 

// in module Y
static class HugeClassExtensions{
    public static void DoModuleYJob(this HugeClass instance){}
}
我发现这不会产生任何编译问题,只要模块Y没有使用DoModuleXJob,反之亦然,这一点我是肯定的


这是一个好的解决方案吗?在这种情况下有没有更好的方法?

扩展方法只是一种“语法糖”。您可以定义公共静态方法,并将HugeClass实例作为其参数之一。
所以这没什么区别。编译后的CIL文件将是相同的。

扩展方法只是一种“语法糖”。您可以定义公共静态方法,并将HugeClass实例作为其参数之一。
所以这没什么区别。编译后的CIL文件将是相同的。

这是一个不错的中间步骤,因为它至少为您提供了一种划分功能的方法,并证明扩展“模块”之间没有方法的相互依赖关系。这是创建真正的子类的伟大的第一步,尽管它仍然不理想(您不能为单元测试单独实例化模块类)

一旦有了这个分区,就应该更容易创建新类,因为您已经确定了模块边界。过程如下:

  • 传递给扩展方法的参数成为新类上的一个字段,该字段在构造函数中设置

  • 所有扩展方法都成为新类的方法

  • 现在可以提取主类的接口,这样子类就不再依赖于完整的实现。在某些情况下,您可以通过将功能分解为多个接口来进一步减少依赖关系

  • 现在通过接口实现了依赖项隔离,您可以为各个模块编写单元测试


  • 这是一个不错的中间步骤,因为它至少为您提供了一种划分功能并证明扩展“模块”之间没有方法间依赖关系的方法。这是创建真正的子类的伟大的第一步,尽管它仍然不理想(您不能为单元测试单独实例化模块类)

    一旦有了这个分区,就应该更容易创建新类,因为您已经确定了模块边界。过程如下:

  • 传递给扩展方法的参数成为新类上的一个字段,该字段在构造函数中设置

  • 所有扩展方法都成为新类的方法

  • 现在可以提取主类的接口,这样子类就不再依赖于完整的实现。在某些情况下,您可以通过将功能分解为多个接口来进一步减少依赖关系

  • 现在通过接口实现了依赖项隔离,您可以为各个模块编写单元测试


  • <>我看到你的设计是不同的,但是为什么你没有使用工作流基础4?这很容易,也很灵活。您可以在工作流中以CodeActivity的形式编写代码。我认为您可以假设工作流(活动)是一个新的模块作业,可以添加到核心

    此外,您还可以动态生成非常有用的工作流(活动)


    (抱歉我的英语不好)

    我看到你的设计是不同的,但是为什么你没有使用工作流基础4?这很容易,也很灵活。您可以在工作流中以CodeActivity的形式编写代码。我认为您可以假设工作流(活动)是一个新的模块作业,可以添加到核心

    此外,您还可以动态生成非常有用的工作流(活动)


    (请原谅我的英语不好)

    我建议您按原样创建设计,将HugeClass中的功能移动到它应该所在的位置,然后将方法调用保留在HugeClass中,但让它按照功能移动到的位置:

    class HugeClass
    {
        [Obsolete("Use ModuleX.DoModuleXJob() instead", false)]
        public void DoModuleXJob() {
            ModuleX mod = new ModuleX();
            mod.DoModuleXJob();
        }
    }
    class ModuleX
    {
        public void DoModuleXJob() {
        }
    }
    
    通过这种方式,随着时间的推移,您将使用HugeClass。我对HugeClass方法应用的警告意味着每次编译调用HugeClass中方法的内容时,都会生成一个警告,指向新功能所在的位置。属性中的“false”参数使其成为警告,可以将其更改为true使其成为错误。通过这种方式,您不需要做太多额外的工作,它代表了向您想要的方向的进步,我不相信您的扩展方法技术一定会做到这一点。随着时间的推移,HugeClass中的方法可以被删除,直到它是一个空类并且它本身可以被删除


    顺便说一句,如果你没有读过马丁·福勒的书,这本书是一本极好的读物。在这篇文章中,他讨论了这一点和许多其他技术。

    我建议您按原样创建设计,将HugeClass中的功能移动到它应该所在的位置,然后将方法调用留在HugeClass中,但让它按照功能移动到的位置:

    class HugeClass
    {
        [Obsolete("Use ModuleX.DoModuleXJob() instead", false)]
        public void DoModuleXJob() {
            ModuleX mod = new ModuleX();
            mod.DoModuleXJob();
        }
    }
    class ModuleX
    {
        public void DoModuleXJob() {
        }
    }
    
    通过这种方式,随着时间的推移,您将使用HugeClass。我对HugeClass方法应用的警告意味着每次编译调用HugeClass中方法的内容时,都会生成一个警告,指向新功能所在的位置。属性中的“false”参数使其成为警告,可以将其更改为true使其成为错误。在