Visual Studio Express: 实现同一套代码针对不同平台工程的编辑和编译
0. 概述和Portable Class Library
首先这里说的内容不是Visual Studio中工程属性的Target framework编译:
工程属性的Target framework仅仅是针对同一个平台的不同Runtime版本。
这里讲的是同一套代码,可以针对不同平台,也就是不同Visual Studio Express程序的工程文件。
在继续之前,必须先提一下微软的Portable Class Library。这也是所有用户应该优先考虑的方式。
用户编译一次针对Portable Class Library的函数库后,整个工程就可以顺利运行在.NET,Silverlight,Window Phone,WinRT(.NET for Windows Store apps)甚至是XBox上。(细节请参考:MSDN)
当然Portable Class Library也不是万能的,我总结有如下几点缺陷:
1. 工程模板限制在Visual Studio的非Express版中。
2. 部分平台有版本限制。比如.NET桌面平台的最低版本必须是4.0。
3. 只支持部分通用的.NET类库子集(大多数是BCL相关的)。
而目前我正在写的Mgen Rfi工程 2.0,最低可支持.NET 2.0,同时我一直只使用Visual Studio Express,所以不适合使用Portable Class Library。决定使用另一种方法,这种方法其实在许多其他类库中都看到过,比如Json.NET,MVVM Light等。
返回目录1. 配置工程属性
OK,现在,比如我写好了.NET桌面平台的类库,他的源代码就够目前是这样的,最上面文件夹是类库的名称(本例中的Mgen.Rfi),下面两个文件夹是Demo。
然后使用Visual Studio Express for Windows Desktop打开整个工程解决方案,我们需要在当前平台的工程中做一些修改。
在工程属性的Build选项卡中设置如下两项:
1. 在General - Conditional compilation symbols中加入当前平台标识,比如NET20(代表.NET 2.0)。
2. 在Output – Output path中设置当前平台标识的目录。比如bin_NET20。
接着切换Configuration Manager的配置项,确保所有配置项(如Debug和Release)都设置了上面两步。
最后保存。
返回目录2. 修改AssemblyInfo.cs
接着,打开工程的AsssemblyInfo.cs文件:
使用C#中的#if等预处理指令通过判断不同平台并加入不同的信息,比如这样:
#if NET20
[assembly: AssemblyTitle("Mgen Rfi Project for .NET 2.0")]
#elif WP7
[assembly: AssemblyTitle("Mgen Rfi Project for Windows Phone 7")]
#endif
3. 修改当前工程名称
接着把当前工程以及解决方案的名称都加入当前平台的标识,如下:
修改后工程源代码目录变成了这样:
返回目录4. 建立另一个平台的工程
接下来,在另一个平台的Visual Studio Express中创建相应的工程。比如打开Visual Studio Express for Windows Phone,创建工程,选择Class Library:
创建完成后,删除Visual Studio Class Library模版默认创建的没用的Class1.cs文件,此时解决方案是空的:
这里也可以加入一个类库的Demo,当然这个步骤是可选的。加完Demo后,解决方案是这样子:
接下来重复上面“1. 配置工程属性”的步骤,按照要求,设置当前平台的工程属性。如下结果:
(注意Configuration Manager中的Debug和Release配置项都要设置)
此时还需要设置工程的AssemblyInfo.cs吗?
当然不需要了,这里只需要设置工程的属性,工程内的文件会直接使用第一个工程的文件(本例中.NET 2.0平台的文件)!
返回目录5. 将两个平台的工程整合到一块
接下来就需要把两个平台的工程文件整合到一块了。首先打开第二个工程的源代码根目录(本例中刚才创建的WP7工程的文件夹):
这里需要做两个任务。
1. 除了类库工程的文件夹(本例中的Mgen.Rfi.WP7文件夹),把其他文件夹和文件复制到第一个工程(本例中的.NET 2.0平台工程)解决方案目录下。
(这个suo文件其实是本地Visual Studio解决方案用户选项文件,也可以不复制)
操作完成后,第一个工程(本例中的.NET 2.0平台工程)根目录是这样的:
(被选中的项目是刚才加入的项目)
2. 把类库工程的文件夹(本例中的Mgen.Rfi.WP7文件夹)中的工程文件选中后复制到第一个工程(本例中的.NET 2.0平台工程)的类库文件夹(本例中的Mgen.Rfi文件夹)下:
(这个user文件也是工程的用户配置文件,可以不复制)
操作完成后,第一个工程(本例中的.NET 2.0平台工程)的类库文件夹(本例中的Mgen.Rfi文件夹)是这样的:
(被选中的项目是刚才加入的项目)
返回目录6. 修改第二个工程的解决方案文件
工程文件夹结构处理好后,在整合后的解决方案根目录下选中第二个工程的解决方案(也就是本例中的WP7工程):
使用记事本打开这个文件,我们需要修改他。
为什么?因为创建解决方案时,类库工程目录的名称就是解决方案的名称(本例中的Mgen.Rfi.WP7文件夹),这个名称是有平台标识的,而把第二个工程整合到第一个工程中后,这个类库的名称是没有平台标识的(本例中的Mgen.Rfi文件夹),因为此时这个类库文件夹代表着跨平台的代码。但是这样的话,原来第二个工程的解决方案会无法定位到类库的工程,所以需要修改第二个工程的解决方案文件。否则解决方案不会成功打开类库的工程。
打开记事本后:
找到子工程的相对路径引用(本例中是“Mgen.Rfi.WP7Mgen.Rfi.WP7.ccsprog”),把它引用的带有平台标识旧目录(本例中的Mgen.Rfi.WP7)改成新的没有平台标识的类库名称(本例中的Mgen.Rfi)。
修改后是:
注意别忘了保存!
返回目录7. 把第一个工程的源代码加入到第二个工程中
修改好第二个工程的解决方案文件后,打开第二个工程的解决方案(本例中会使用Visual Studio Express for Windows Phone),此时类库文件会被成功打开,但是不会有任何文件:
接下来,选中类库工程(本例中的Mgen.Rfi.WP7工程),在Solution Explorer上选择Show All Files:
然后源代码文件会全部出现,接着选中需要的文件,右键,选择Include In Project:
第一个平台工程的源代码文件就会加入到第二个平台工程中了。
返回目录8. 预处理指令消除编译问题
上面步骤全部完成后,就可以对第二个平台的工程进行编译了,如果有任何编译错误,请使用预处理指令解决,方法类似”2. 修改AssemblyInfo.cs“提到的方式。
比如,在桌面环境下配置数据可能存储在文件中,而在Windows Phone 7环境下配置数据可能存储在独立存储中,所以需要使用预处理指令区分平台来实现不同平台的不同代码编译:
#if NET20
//桌面读取配置文件
#elif WP7
//WP7访问独立存储
#endif
OK,最终我们实现了,同一份代码,在不同Visual Studio Express支持的平台上进行编辑和编译!
作者:Mgen
出处:www.cnblogs.com/mgen
其他参考页面:我的软件和工程,博客导读。