zoukankan      html  css  js  c++  java
  • 实现针对不同.net版本的条件编译

    今天碰到这样一个需求,写的C#库,有时候需要在.net 2.0下编译,有时候需要在.net 4.0下编译,这个库里使用了lambda表达式,使用了扩展方法,使用了几个 System.Core.dll 引入的Action类型。

    为了在 .net 2.0 下能够编译成功,我写了一个文件 Patch.cs,定义了 System.Runtime.CompilerServices.ExtensionAttribute  类型,这样就可以在2.0下使用lambda表达式和扩展方法了,同时,添加了几个用到的System.Core.dll 引入的Action类型:

     1:  namespace System.Runtime.CompilerServices
     2:  {
     3:      public class ExtensionAttribute : Attribute { }
     4:  }
     5:  
     6:  namespace System
     7:  {
     8:      public delegate void Action();
     9:      public delegate void Action<T0,T1>(T0 t0,T1 t1);
    10:  }
    11:  

    然而,要在.net 4.0 下编译,因为类型已经存在,必须注释掉Patch.cs,很麻烦。于是想通过条件编译来解决,即:

     1:  #if NET2
     2:  
     3:  namespace System.Runtime.CompilerServices
     4:  {
     5:      public class ExtensionAttribute : Attribute { }
     6:  }
     7:  
     8:  namespace System
     9:  {
    10:      public delegate void Action();
    11:      public delegate void Action<T0,T1>(T0 t0,T1 t1);
    12:  }
    13:  
    14:  #endif

    问题是,.net 里没有定义和.net版本有关的指示符。怎么办呢?自己动手,丰衣足食,使用Build Events在编译之前自动侦测出项目所使用的.net版本,定义出我们想要的指示符。

    在  C#模板编程(2): 编写C#预处理器,让模板来的再自然一点 一文中,写了一个程序 Csmacro.exe 来实现C#下的模板机制,本文在Csmacro.exe 的基础上,增加侦测项目所引用的.net 版本的功能。

    原理:查找项目目录下的 csproj 文件,解析它,找到节点TargetFrameworkVersion,判断.net版本,然后生成一个Csmacro_Template.cs文件,在里面 #define 版本指示符。例如,对 .Net 2.0 项目,生成的 Csmacro_Template.cs 文件内容为:

    #define NET2

    修改后Csmacro的代码可在:https://github.com/xiaotie/GebCommon 上下载(目前只处理了 .net 2.0 和 4.0,如需要针对其它版本,可自行修改代码)。有了 Csmacro,一切就好办了。

    第一步,把 Csmacro.exe 放在Path路径下

    第二步,打开需要条件编译的项目,添加 Pre-build 事件:Csmacro.exe $(ProjectDir)

    第三步,编辑源文件,如,Patch.cs 文件修改为:

     1:  #region include "Csmacro_Template.cs"
     2:  #endregion
     3:  
     4:  #if NET2
     5:  
     6:  namespace System.Runtime.CompilerServices
     7:  {
     8:      public class ExtensionAttribute : Attribute { }
     9:  }
    10:  
    11:  namespace System
    12:  {
    13:      public delegate void Action();
    14:      public delegate void Action<T0,T1>(T0 t0,T1 t1);
    15:  }
    16:  
    17:  #endif

    #region include 是我引入的 Csmacro 宏语法。详见 C#模板编程(2): 编写C#预处理器,让模板来的再自然一点 一文。点击编译,系统会生成一个 Patch_Csmacro.cs 文件,内容如下:

     1:  #define NET2
     2:  
     3:  #if NET2
     4:  
     5:  namespace System.Runtime.CompilerServices
     6:  {
     7:      public class ExtensionAttribute : Attribute { }
     8:  }
     9:  
    10:  namespace System
    11:  {
    12:      public delegate void Action();
    13:      public delegate void Action<T0,T1>(T0 t0,T1 t1);
    14:  }
    15:  
    16:  #endif

    第四步,把生成的 Patch_Csmacro.cs 添加到项目中来。

    搞定以后,选择不同的target,编译时产生的就是对该target的条件编译!

  • 相关阅读:
    WCF初探-21:WCF终结点(endpoint)
    WCF初探-20:WCF错误协定
    WCF初探-19:WCF消息协定
    WCF初探-18:WCF数据协定之KnownType
    WCF初探-17:WCF数据协定之等效性
    WCF初探-16:WCF数据协定之基础知识
    WCF初探-15:WCF操作协定
    WCF初探-14:WCF服务协定
    WCF初探-13:WCF客户端为双工服务创建回调对象
    WCF初探-12:WCF客户端异常处理
  • 原文地址:https://www.cnblogs.com/xiaotie/p/2789810.html
Copyright © 2011-2022 走看看