C# 如何编写使用某些库的不同版本的代码,这些库在编译时不会进行任何代码更改

C# 如何编写使用某些库的不同版本的代码,这些库在编译时不会进行任何代码更改,c#,C#,我希望能够编写一个使用库中代码的函数,让我们调用它libx,而无需根据我使用的libx版本更改代码 比如说 public string ReturnFormattedString(string input) { //If using version 1 of library return libx.SomeClass.FormatString(input); //If using version 1 of library //If using version 2

我希望能够编写一个使用库中代码的函数,让我们调用它libx,而无需根据我使用的libx版本更改代码

比如说

public string ReturnFormattedString(string input) {
    //If using version 1 of library
    return libx.SomeClass.FormatString(input);
    //If using version 1 of library

    //If using version 2 of library
    return libx.SomeNewClass.FormatString(intput); 
    //Note: libx.SomeNewClass is not available in version 1
    //If using version 2 of library
}
我甚至不确定这是否可行,但我想知道如何实现这一点,这样我就可以编译代码,而不必根据使用的libx版本进行任何更改

编辑:

只是为了澄清一些事情。我没有访问libx代码的权限。我的应用程序是在另一个使用libx的程序上运行的插件。所以libx的版本取决于我插入的程序的版本


我开始认为,如果没有两个不同的程序集,每个程序集都有不同的ReturnFormattedString实现,这可能是不可能的,这取决于我首先要避免的libx版本。

在这种情况下,您返回的是一个字符串,因此,即使代码发生了更改,调用方也看不到实现更改。但是,通常可以使用基于接口的编程:

public string ReturnFormattedString(string input, iSomeClass myInjectedClass) {
    //If using version 1 of library
    return libx.myInjectedClass.FormatString(input);
    //If using version 1 of library

    //If using version 2 of library
    return libx.myInjectedClass.FormatString(intput); 
    //Note: libx.SomeNewClass is not available in version 1
    //If using version 2 of library
}
现在,调用方通过依赖项注入定义实现

结合良好的OO设计,您就有了实现开闭原则的可维护代码的最佳可能性


当然,现实的范围蠕变和/或需求变更最终可能导致合同变更违约。这就是生活。

因为一个项目在某个地方需要一个硬依赖,我不推荐一个项目支持,除非您添加每个DLL作为参考

您当然可以使用@p.Brian.Mackey提到的高级设计模式来抵消成本和复杂性,例如依赖注入。我是使用设计模式解决代码复杂性的支持者。然而,如果您正在谈论处理几个类,那么这可能会很麻烦,因此范围在这里很重要。或者,您的大部分代码可以是一个中央库,它可能是也可能不是PCL,并且只有差异存在于子项目中,每个版本对应一个

也可以按照您的要求执行,每个版本都有一个单独的项目,使用自定义条件符号。在VS Project settings>Build选项卡中,有一个条件编译符号文本框,您可以在其中执行以下操作:

#if VERSION1
#else
#endif

并使用它来根据目标框架改变逻辑。然后,您所要做的就是更改符号,或者将代码放在一个文件夹中,并在那里有多个指向同一代码的项目文件,每个文件都有自己的编译符号。这可能会很乏味,因为你必须不断地映射文件,但你可以使用类似于这样的工具来管理它。

反射确实是实现这一点的唯一方法。。。尽管如此,我不认为你能保证它永远不会破裂。如果您可以访问库中的代码,可能还有其他一些方法来获得您想要的,但是无论哪种方法,您都必须在某个时候更改代码。通常情况下,库的编写者不会因为这个原因而更改类名。人们希望库是向后兼容的,因此如果要用旧版本的方法编写所有内容,如果他们有更新的版本,为什么不使用所有这些代码?为什么不在新程序集中打包SomeNewClass?似乎您在寻找MEF?是否尝试使用alias关键字?但这不是一个选择。事实上,这个库需要以两个库作为依赖项进行编译,因此当使用该库的人使用它时,如果他们没有这两个库,他们将得到错误。没有真正有效的方法告诉C编译器,我只需要这两个库中的一个。您可以动态加载程序集,但随后您需要在反射中完成全部编码,而不是编译后的代码。只需添加依赖项注入即可。向函数添加一个参数,以便调用方在接口中传递。当您决定是否在运行时使用依赖项时,这不起作用。这只是在决定编译时使用什么依赖项时的一个选项。还请记住,此方法的调用方被设计为不知道此行为,而不是调整其调用方法的方式。如果这是一个选项,您只需创建两个不同的程序集,一个针对依赖项的每个版本。可能是错误的。。。我不相信OP指的是运行时动态变化的支持;我认为这是一个方便的功能。依赖注入很可能是一个好的选择。这导致能够创建两个版本的库,一个针对每个框架,这与使用两个外部库中任何一个的单个库非常不同。同样,这仍然不是OP所要求的,哪个是使用适当dep的单个程序集
亲昵。创建两个不同的程序集,每个依赖项一个,这是他明确表示不想做的事情。我需要创建一个使用适当依赖关系的程序集。如果您想要类型专用性,但不是将每个DLL添加为硬引用,那么您无法执行您想要执行的操作。否则,您将需要使用反射来根据程序集列表中libx的版本加载程序集,并使用反射来调用API上的方法,这将丢失类型特定性。