2009-07-01 23 views
2

我正在为log4net开发一个appender,我面临着如何管理log4net版本依赖关系的问题,我的类库针对的是部署的实际版本网站。我的类库必须引用log4net dll,因此它将与我在构建时引用的版本绑定。然而,这个组件将被部署的站点将有不同的log4net版本,有些比我的要早,有些会更新。我应该如何处理这个问题?我不想为每个log4net新版本发布我的appender的新版本,并将正确匹配它们的负担放在我的用户身上。我也不想问我的appender用户做复杂的并行清单技巧。我只希望我的appender能够简单地复制到最终用户位置,并且可以随时随地使用任何log4net版本。托管类库中与版本无关的引用依赖关系

这是可以实现的吗?我错过了明显的东西吗?

更新

唯一的工作解决方案是使用清单。我有两个“自制” log4net的测试,建立并添加以下配置部分解决了我的问题:

<runtime> 
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <dependentAssembly> 
      <assemblyIdentity name="log4net" 
           publicKeyToken="..." 
           culture="neutral" /> 
      <bindingRedirect oldVersion="1.2.10.0" 
          newVersion="..."/> 
     </dependentAssembly> 
     </assemblyBinding> 
    </runtime> 

其中公钥是真正的log4net程序集的实际密钥令牌,1.2.10是我的appender是内置的版本with和newVersion是现场部署的版本。该部分可以添加到部署的appconfig或webconfig(它也可以在机器配置中完成,但我不建议......)。

回答

2

很多项目都有与刚才描述的相同的问题。据我所知,这不是你作为发布商可以控制的东西。您可以设置一个publisher policy,允许您自动指定在引用较旧版本的程序集时应使用某个版本的程序集,但无法为不控制的程序集(如log4net)指定此版本。

在用户端,管理员可以通过assembly redirect将指定的旧版log4net(您的程序集可能引用)的请求重定向到特定版本。

+0

我知道你的回答是对的,但是我试图避免的一个问题是(让我的客户编辑清单文件) – 2009-07-06 20:11:20

0

编辑:下面的建议不工作:(!假设你使用Visual Studio)的具体版本是在编译时,不执行时间

选择在Visual Studio中参考log4net的应用并显示属性。设置“特定版本”为“假”,我认为你应该没问题。你是否已经尝试过并遇到过问题?

+0

经过9年的.NET工作,我第一次听到选项*存在*。我会试一试。 – 2009-07-03 23:23:53

+0

我真的很想知道这是否适合你。如果我没有记错的话,Fluent NHibernate(或NHibernate本身)会因为OP中描述的问题而放弃对log4net的依赖。 – 2009-07-03 23:30:35

+0

我在log4net v1.2上留下了一个'软'依赖的appender dll。然后我编译了一个更新的log4net v1.9并运行我的测试。它拒绝加载我的appender,并显示消息'无法加载文件或程序集'log4net,Version = 1.2.10.0,...'。我也尝试了另一种方式(我的'v1.9',运行时v1.2构建的appender)无济于事。我删除了强名,结果相同。基于http://bit.ly/4ViOa,我认为这个'错误'只适用于编译时间。 – 2009-07-04 04:32:27

0

可以使用一个容器IoC(如CastleSpring.net等)实际实例化所需的类你,根据所使用,如在一个配置文件(或代码片段)定义的接口。
这样,您只能使用接口,而具体类的实际绑定是由容器(框架)完成的。如果您使用dependency injection(关于它也参见Fowler's article),这是(特别是)可实现的。
只要您使用的接口保持不变,您就可以对代码进行“后期绑定”。

2

你可以处理AssemblyResolve事件:

AppDomain current = AppDomain.CurrentDomain; 
current.AssemblyResolve += current_AssemblyResolve; 

然后,您可以使用name属性(从ResolveEventArgs)字符串操作删除版本号和加载程序集,而不指定它的版本。

0

简单而愚蠢的解决方案将是使用vb.net上编写的代理库。

当我试图为MS OFFICE构建工具时遇到了类似的问题。

与VB我不担心安装什么版本的办公室。

0

我倾向于强烈不喜欢图书馆,当它们的主要目的没有明确要求时,依赖基础架构库,比如单元测试框架,日志框架和代码生成工具。

如果您要依赖一个可以在GAC中安装的库,那么您可以依赖该库并同时激活该库的多个版本,但这可能无法与log4net一起运行良好(因为共享常用的配置状态模型),并增加了使用库的复杂性。

有人可以指出,许多库不应该输出任何类型的日志记录,因为他们将无法足够好地预测其用户的需求。尽管如此,log4net的运行时可配置性在一定程度上确实缓解了这一点。如果它转向使用内置于框架中的Tracing api,您的代码会更好吗?由此产生的代码在依赖性方面变得更加轻量级,并且仍然允许一些复杂的调优后编译。

0

替代我的其他答案。 Hacky,并且可能有复杂性,但是:

将log4net代码构建到您的dll中。
由于它是开源的,并且在reasonably permissive licence下,您可以编辑这些文件(注意您已经这样做)来更改可见性(以及可选的命名空间),以便它可用于您的代码并且不会影响用户。

您可能希望添加一些代码以尝试从应用程序的其余部分配置您的库,或者(并且更容易理解)允许配置从完全独立的文件/配置节。

0

对于CAD/CAM应用程序,我不得不面对与我们不得不支持的第三方机器的一些支持库的问题。我做了什么,我创建了两个程序集,一个链接到一个版本,另一个链接到另一个版本。我把它们放在同一个界面后面。

然后在我们的设置对话框中,您可以指定要使用的版本。当然,如果使用不正确的版本,则会发生错误。

诀窍是创建接口,因此两个程序集都可以无缝工作。可能无法包装像Microsoft Office这样的复杂API。在这种情况下,您需要回溯您对API的使用,并查看最少使用的调用数量,并在此时构建您的界面。

在我的情况下,当我不得不将一张材料转储到机器上时,所以我创建了一个界面,该界面拥有该机器的安装对话框和一个带有我的工作表对象的例程。一切都在这个班上。

在你的情况下,你需要看看你在Log4net中使用什么,看看你是否可以构建一个接口。

这样做的一个好处是您不再被焊接到Log4Net。正确设计接口,然后重新实现使用不同的包。此外,创建接口将精确定义应用程序与Log4net的交互方式。最后,如果Log4Net实现了重大改变,那么你有一条路径来处理它。

0

值得一提的是,由于1.2.10.0版本和log4net的的1.2.11.0之间的公钥的变化,这bindingRedirect是不可能之间的那些两个版本的原因讨论herehere近了。

如果您使用NuGet,这更是一个问题,因为这意味着您需要绕过NuGet使用可从here下载的log4net的oldkey版本。

然而,我发现,即使失败与下面的异常在aforementioned link提到的原因:未找到

方法:“无效log4net.Config.BasicConfigurator.Configure()”