我应该使用类库来定位.NET Framework和C#版本?
我正在构建一个DLL类库 – 我想让尽可能多的人使用它。 我应该使用哪个版本的.NET Framework和哪个C#版本? 是否有可能为不同版本生成向后兼容的DLL或不同的DLL? 或者Windows是否自动更新.NET框架,所以我应该使用最新版本? 任何指导赞赏!
我们针对某些产品同时针对多个运行时版本(.NET 1.1,.NET 2.0和.NET 3.5)。
我们以几种方式处理这个问题:
- 单独的解决方案和项目文件以及.NET 1.1,2.0和3.5 SP1中的每一个,但引用相同的源文件。
例如:
\ ProductFoo_1_1.sln(.NET 1.1解决方案,VS 2003) \ ProductFoo_2_0.sln(.NET 2.0解决方案,VS 2008) \ ProductFoo_3_5.sln(.NET 3.5解决方案,VS 2008) \ FooLibrary \ FooLibrary_1_1.csproj(.NET 1.1 Project,VS 2003) \ FooLibrary \ FooLibrary_2_0.csproj(.NET 2.0 Project,VS 2008) \ FooLibrary \ FooLibrary_3_5.csproj(.NET 3.5 Project,VS 2008) \ FooLibrary \ FooClass.cs(在所有项目中共享) \ FooLibrary \ FooHelpers_1_1.cs(仅由.NET 1.1项目引用) \ FooService \ FooService_3.5.csproj(.NET 3.5 Project,VS 2008) \ FooService接口\ FooService.cs
-
在每个解决方案中定义
NET_X_X
符号 -
对于.NET Framework特定代码,我们使用预处理器指令,例如:
public void SomeMethod(int param) { #ifdef NET_1_1 //需要在.NET 1.1下使用Helper来获取Foo Foo foo = Helper.GetFooByParam(param); #elseif NET_2_0 || NET_3_5 // .NET 2.0及以上版本可以使用首选方法。 var foo = new Foo {Prop = param}; foo.LoadByParam(); #万一 foo.Bar(); } #ifdef NET_3_5 //仅在.NET 3.5下可用的方法 public int [] GetWithFilter(Func Filter) { //这里有一些代码 } #万一
为了澄清,上面以#开头的行是预处理器命令。 编译解决方案时,C#编译器(csc)预处理源文件。 如果您有#ifdef
语句,则csc将评估以确定是否定义了该符号 – 如果是,则在编译项目时包括该段中的行。
这是一种在某些条件下标记编译代码的方法 – 我们还使用它在特定的详细调试版本中包含更密集的调试信息,如下所示:
#if DEBUG_VERBOSE Logging.Log(“使用参数调用的Web服务:param =”+ param); Logging.Log(“Web服务响应:”+响应); Logging.Log(“当前缓存大小(字节):”+ cache.TotalBytes); //等 #万一
- 然后,我们使用NAnt脚本自动生成每个.NET版本的发行版。 我们碰巧通过TeamCity控制所有这些,但我们也可以手动触发NAnt脚本。
它确实使事情变得更复杂,因此我们只倾向于在需要维护旧版.NET 1.1或2.0实例的地方(例如,客户无法/不会升级)。
我想,当.NET 4.0滚动时,我们会做同样的事情,只需添加一个NET_4_0符号。
就个人而言,我的目标是.NET 2.0。 这意味着,除其他外:
- 没有扩展方法(虽然有解决方法)
-
没有linq
-
你可以使用lambda表达式
- 你可以使用’var’关键字
问题是,您可以使用C#3.x语言function(所谓的语法糖),但您不能使用以C#3.x为目标的库(System.Core为1,包括扩展方法和linq)。
我不会尝试支持C#1.x,因为它与C#2.x及更高版本完全不同。 此外,我希望大多数使用你的图书馆的人都是建立新事物的人,他们不会在正确的思想中使用C#1.x 😉
除非你需要使用3.0或3.5function,否则我会保持2.0。
试试这个:
将目标模式切换到框架2.0(删除System.Core引用)。
如果没有编译,请尝试添加对linqbridge.dll的引用:
如果没有,那么你应该针对3.5;)
如果我要开始一个新项目,我会一直使用最新的运行时! 如果3.5可用,为什么我需要在2.0或1.0中启动项目,除非我知道新版本存在严重错误? 新版本意味着修复旧错误并添加新function,因此这很好。
在将旧项目升级到新版本时,您需要考虑您的收益和损失。 如果它的颜色很高,请升级它,如果不坚持使用旧版本。
请小心,因为新工具可能不支持旧版本。 虽然2010年并非如此,因为它将支持高达2.0的所有版本。
我投票支持Erik van Brakel的回答。 另外我想建议如果你想支持LINQ和扩展方法等3.5function,你可以创建一个额外的库
MyLibrary.DLL
MyLibrary.LINQ.dll
因此使用与MS相同的方法(当他们离开System.dll 2.0版本但将所有新function添加到System.Core.dll中时)
我将使用包含核心function的库来定位2.0版,并添加一个额外的目标库3.5,以根据您的核心库添加一些扩展方法。
从我的角度来看,如果你想要广泛的用户,你应该使用早期版本,1.1会很好,因为它可以在任何机器上运行.Net的版本。
这取决于dll的用途。 如果它只是一个你想让别人可以使用的通用C#逻辑,那么.net 2.0可能是你最好的选择。 但是,如果它与.net中的新function有关,如WPF,EF,WCF,silverlight等,那么它将需要在支持该特定function的.net版本中。
就个人而言,我会说在.net 3.5中编写它只是因为从.net2.0到.net3.5的跳转是非常轻松的,因为与.net1.x跳转到.net2.0不同,没有太多突破性的变化。 🙂
我认为不再有人使用.Net 1.1了。 所以,除非你真的想使用3.5function2.0应该没问题。 此外,如果您可以控制谁将实际使用您的库,那么它也取决于它们。 如果他们有最新的框架,那么你可以使用它。
结合使用Will Hughes提到的方法,如果您希望访问/选项在可用时使用更新的function,则在活动开发期间,使用最新的框架。 当准备好开始发布候选版本时,设置为最低框架,然后当问题到达时,稳定地提升框架版本和/或使用#ifdef方法来解决问题。
这个解决方案效果很好。 我只是设置了两个不同的项目,每个项目都有一个独特的“Project Properties-> Build-> Conditional compilation Symbols”,并在代码中使用如下:
#if NET_4 xmlReaderSettings.DtdProcessing = DtdProcessing.Ignore; #endif #if NET_3_5 xmlReaderSettings.ProhibitDtd = false; #endif