基于C#中类库版本的条件编译

时间:2014-03-31 12:59:51

标签: c# compiler-construction

在经典C中,我可能有一个版本1.0的库,它在.h文件中定义了一个常量,如:

 #define LIBRARY_API_VERSION_1_0

我可以在我的应用程序代码中执行以下操作:

#include "LibraryApi.h"
// ...
int success; 
#ifdef LIBRARY_API_VERSION_1_0
    int param = 42;
    success = UseThisMethodSignature(42);
#endif
#ifdef LIBRARY_API_VERSION_2_0
    float param = 42.0f;
    success = UseOtherMethodSignature(param);
#endif

现在我在C#工作。所以,显然#define只限于它们定义的文件范围,因此我研究了使用带常量的静态类的解决方案described here。但是,该解决方案需要在运行时进行检查,这会引入许多问题:

  • 潜在的低效率,如果我一遍又一遍地运行相同的代码检查一个额外的条件(尽管它是const,也许编译器或.NET运行时很聪明到避免这种情况?)
  • 你不能做会导致编译错误的事情。在上面的例子中,我用两种不同的类型定义了param两次。此外,UseOtherMethodSignature可能不作为函数存在,如果两个块仅由if / else分隔,则不会编译。

那么,这类问题的解决方案是什么?我的情况是我有多个版本的Web服务API(根据您使用它做的不同,会有不同程度的差异),我希望能够在不注释/取消注释一堆代码的情况下进行编译。其他一些同样愚蠢的手工流程。

修改

为了它的价值,我更喜欢编译时的解决方案 - 在我的场景中,我知道当我编译我要使用的版本时,我不会需要确定在运行时系统上哪个版本的库可用。是的,这会有效,但看起来有点矫枉过正。

3 个答案:

答案 0 :(得分:1)

我的目标是将其抽象为不同的包装库。它们将是Visual Studio中的单独项目,并引用框架的不同版本。

// Shazaam contract.
public interface IShazaamInvoker {
    Boolean Shazaam();
}

// ShazaamWrapper.v1.dll implementation
public class ShazaamInvoker : IShazaamInvoker {
    public void Shazaam() {
        Int32 param = 42;
        return UseThisMethodSignature(param);
    }
}

// ShazaamWrapper.v2.dll implementation
public class ShazaamInvoker : IShazaamInvoker {
    public void Shazaam() {
        Single param = 42f;
        return UseOtherMethodSignature(param);
    }
}

// Determine, at runtime, which wrapper to use.
var invoker = (IShazaamInvoker)(/*HereBeMagicResolving*/)
invoker.Shazaam();

答案 1 :(得分:0)

我建议使用DI框架加载适当的类/ dll。如果您可以重构代码以使用接口,那么您可以跨不同版本创建抽象层。有关可用的不同框架,请参阅this链接。

或许另一个与您的问题的编译时间性质保持一致的解决方案是使用生成的代码T4

答案 2 :(得分:0)

您必须在项目级别定义编译符号。您可以在项目属性中执行此操作。可以使用#if指令引用这些符号。

您还可以创建包含一个或另一个编译符号的项目构建配置,并检查项目文件中的配置以包含基于符号的一个或另一个.dll引用,以便您可以正确地构建和调试两者版本只需从工具栏的下拉列表中选择版本。