C# 如何对中间层.NET应用程序类/方法进行版本设置

C# 如何对中间层.NET应用程序类/方法进行版本设置,c#,.net,versioning,asp.net-web-api2,C#,.net,Versioning,Asp.net Web Api2,我们有一个典型的N层.NET应用程序,它位于数据库和Web API服务层之间。此应用程序由业务层、数据存储库/访问以及相关的DTO和业务对象组成 我们有适当的解决方案来版本化存储过程和Web API端点。问题是这个中间层的版本、实际的类方法和模式对象的解决方案。所有谷歌搜索都会给出源代码控制解决方案中源代码版本控制的结果,或者如何使用程序集信息进行版本设置的结果,这两者都不是我们所指的,因此结果是有限的 例如,我们有两个端点: …api/v1/税/费 …api/v2/税/费 v1必须命中Calc

我们有一个典型的N层.NET应用程序,它位于数据库和Web API服务层之间。此应用程序由业务层、数据存储库/访问以及相关的DTO和业务对象组成

我们有适当的解决方案来版本化存储过程和Web API端点。问题是这个中间层的版本、实际的类方法和模式对象的解决方案。所有谷歌搜索都会给出源代码控制解决方案中源代码版本控制的结果,或者如何使用程序集信息进行版本设置的结果,这两者都不是我们所指的,因此结果是有限的

例如,我们有两个端点:

…api/v1/税/费
…api/v2/税/费

v1必须命中CalculateExpctgs方法的一个版本,v2命中更新了业务逻辑的另一个版本。随着我们在v2中更改了一个字段的名称,两者都需要使用不同版本的POCO-Tax和TaxItems

易于开发但难以管理且非常严格/静态的解决方案是创建两种不同的方法,CalculateExpctgs_V1和CalculateExpctgs_V2。这似乎不是个好主意


很难找到解决这一困境的最佳实践或替代方案。这是一个每天需要数百万次请求的企业应用程序,因此性能非常重要,而代码管理和可靠性也非常重要。

显然,这取决于解决方案的具体组合方式,但重定向程序集版本是否是您可以利用的:

您可以通过多种方式重定向应用程序以使用程序集的不同版本:通过发布者策略,通过应用程序配置文件;或通过机器配置文件


我将使用对象继承而不是不同的方法。这样,如果一个方法在不同版本之间保持不变,则不需要以任何方式更改实现。然后,您可以使用某种工厂来创建所需的实例。例如:

public virtual class TaxCalculatorBase {
    public virtual ICollection<TaxPercentage> CalculateTaxPercentages() {
        DefaultImplementation();
    }
}

public sealed class TaxCalculatorV1 : TaxCalculatorBase {
    //Same implementation so no need to override
}

public sealed class TaxCalculatorV2 : TaxCalculatorBase {
    //Same implementation but with a bit extra
    public override ICollection<TaxPercentage> CalculateTaxPercentages() {
        base.CalculateTaxPercentages();
        ExtraStuff();
    }
}

public sealed class TaxCalculatorV3 : TaxCalculatorBase {
    //Different implementation
    public override ICollection<TaxPercentage> CalculateTaxPercentages() {
        NewImplementation();
    }
}

public static class TaxCalculatorFactory {
    public static TaxCalculatorBase Create(int version) {
        switch (version) {
            case 1: return new TaxCalculatorV1;
            case 2: return new TaxCalculatorV2;
            case 3: return new TaxCalculatorV3;
            default: throw new InvalidOperationException();
        }
    }
}

public class CallingClass {
    public void CallingMethod(int versionFromURL) {
        var calculator = TaxCalculatorFactory.Create(versionFromURL);
        var percentages = calculator.CalculateTaxPercentages();
        percentages.DoStuffWithThem();
    }
}

为了解决这个问题,我们实现了动态加载程序集,它可以处理80多个不同的版本。它工作得很好。我们不会更改已部署的软件(除非存在严重缺陷),因为它是生产系统的一部分,一旦正常工作,我们就无法破坏它


随着时间的推移,我们也有一些重要的变化,比如使用几个不同版本的.NET。要处理此问题,我们将请求路由到不同的应用程序部署。

如何处理版本中的参数类型/计数更改?为什么所有版本的TextCalculator都继承自TextCalculatorBase对象?您需要重新编写一些方法,例如v1有方法get(),v2有方法get()和get()方法与v1和v2完全相同。如果您像vn:vn-1一样使用v2:v1继承可能是更好的解决方案?如前所述,它是一个web api应用程序,因此我们需要查询请求、识别版本并动态加载一组不同的程序集。我们已经考虑过这一点,但我们不能使用应用程序或机器配置,因为它是动态的。如果这是最好的方法,那么我们真的希望在现实世界中实现这一点,我们关心的是每天收到数百万请求的应用程序的动态负载的性能。您是否使用过它或只是建议使用它?我没有在这种情况下使用过它-并且无法为您提供真实世界的实现。它只是觉得它可能会提供一个解决方案。如果不行,我可能会使用非标准的动态加载(可能使用基于版本号的目录结构)。对不起,帮不上什么忙。不过祝你好运。我很好奇,你能详细介绍一下你使用的动态程序集加载的实现吗?什么类型的应用程序以及在应用程序中的什么位置加载正确的程序集?组件位于何处?您如何管理不同的版本,包括命名方案以及如何将正确的程序集版本映射到应用程序的每个版本?Keith-您有关于实现的详细信息吗?
public static class MyFactory {
    public static TaxCalculatorBase CreateTaxCalculator(int version) {
            switch (version) {
                case 1: return new TaxCalculatorV1;
                case 2: return new TaxCalculatorV2;
                case 3: return new TaxCalculatorV3;
                default: throw new InvalidOperationException();
            }
        }
    }
    //various other methods to create classes which depend on version
}