库中的嵌入式引用 [英] Embedded references in library

查看:86
本文介绍了库中的嵌入式引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的......努力将一些库转移到.Net Standard SDK。出现了一些我多年来一直在考虑的事情,但直到现在才被迫解决。我已经成为C#的开发人员已经有15年了,这感觉就像一个新手必须解决的问题所以我有点不好意思问这个问题。但我的Googlefu迄今尚未透露任何有效的解决方案。无论如何这是我的boggle。



图书馆A:包含接口。一个这样的接口允许编码器将连接包装到excel电子表格。



库B:包含这些接口的实现。虽然细节并不特别重要。库B特别使用EPPLUS。有关更多详细信息,我通过Nuget获取EPPLUS库。



库C:包含正确加载配置文件指定的任何实现库的代码,并将该实现交还给可执行代码。



可执行代码:实际利用界面进行工作的代码。



配置文件:该文件指定可执行代码应该使用库B来完成它需要做的事情。





现在。 ..从可执行代码的角度来看......它不知道或关心什么实现库被加载。它所知道的是,它将使用一个接口来完成它的工作。在这种情况下,可执行代码根本不应该对库B进行任何引用。库B应该驻留在可执行加载可以按照指示加载它的某个地方。像运行时目录或GAC一样。可执行代码应该只能直接引用库A和库C.



在运行时,可执行代码使用库C中的加载器获取适当的实现并使用用于在指定路径打开excel工作簿的界面。它并不关心如何完成它,只是它是如此。现在我的可执行代码只是一个单元测试。它当然不需要了解EPPLUS ...



问题:

如果可执行代码不包含直接引用EPPLUS,当库B实现尝试加载EEPLUS时,整个过程将崩溃。这就是说,如果可执行文件在解决方案资源管理器中没有Nuget引用或者它的引用节点中至少有一个引用,那么该程序将无法运行,您将获得一个'

 System.IO。 FileNotFoundException:'无法加载文件或程序集'XXXX,Version = YYYY,Culture = neutral,PublicKeyToken = ZZZZ'或其依赖项之一。系统找不到指定的文件。'

'例外。



现在你可以尝试通过在main上使用AssemblyResolve事件来解决这个问题。应用域名。但是,因为在运行时目录中包含Epplus.dll并不意味着您可以使用或者可以加载Epplus所依赖的十个左右的程序集。



所以当你的AssemblyResolve甚至开火时,你可以加载Epplus。但是你没有加载它的要求。因此,您将 - 仍然 - 获取FileLoadException。



现在您可以将Epplus.dll库嵌入库B并从资源流加载它。这种方法的问题在于,每当Epplus库发生变化时,您都需要重新编译库B,但仍然无法获得所有Epplus的参考。



Nuget当然会处理所有这些...但是需要你发送你的可执行代码,直接引用Epplus,这会破坏关注点分离的整个概念。更糟糕的是,如果你有十个不同的实现库,你的可执行文件将需要引用它们,即使用户从不使用它们。



我尝试过的:



在库B中嵌入参考库并在AssemblyResolve事件期间加载它。

解决方案

GitHub - Fody / Costura:将引用作为资源嵌入 [ ^ ]

NuGet画廊| Costura.Fody 1.6.2 [ ^ ]

Ok so...Working on moving some libraries over to the .Net Standard SDK. Something came up that I'd been thinking about for years but was never compelled to fix until now. I've been a developer in C# for something like 15 years and this feels like a problem a newb would have to tackle so I'm a little embarrassed to ask this question. But my Googlefu has not revealed any solutions thus far that have worked. Anyway here's my boggle.

Library A: Contains interfaces. One such interface allows the coder to wrap the connection to an excel spreadsheet.

Library B: Contains implementations of those interfaces. While the details don't particularly matter. Library B in particular uses EPPLUS. For more detail, I am getting the EPPLUS libraries through Nuget.

Library C: Contains the code to properly load whatever Implementation library the configuration file specifies and hand that implementation back to the executable code.

Executable code: The code that actually utilizes the interface to do work.

Configuration File: The file specifies that the executable code should use Library B to get done what it needs to do.


Now... from the perspective of the Executable code... it doesn't know or care anything about what implementation library gets loaded. All it knows is that it's going to use an interface to do it's work. That being the case, the executable code shouldn't have any reference at all to Library B. Library B should just reside somewhere where the executable load can load it as directed. Like the runtime directory or the GAC or something. The executable code should only have a direct reference to Library A and Library C.

At runtime, the Executable code acquires the appropriate implementation using the loader in Library C and uses the interface to open an excel workbook at a specified path. It doesn't care how this gets done, only that it is. Right now my executable code is just a unit test. It certainly doesn't need to know anything about EPPLUS...

The Problem:
If the executable code doesn't contain a direct reference to EPPLUS, the whole thing will crash the moment the Library B implementation tries to load EEPLUS. This is to say that if the executable doesn't have a Nuget reference or at least a reference in it's reference node in the solution explorer the program will not work and you'll get a '

System.IO.FileNotFoundException: 'Could not load file or assembly 'XXXX, Version=YYYY, Culture=neutral, PublicKeyToken=ZZZZ' or one of its dependencies. The system cannot find the file specified.'

' exception.

Now you can attempt to remedy this by using an AssemblyResolve event on the main app domain. However, because having the Epplus.dll in your runtime directory doesn't mean you have handy or can load the ten or so assemblies that Epplus relies upon.

So when your AssemblyResolve even fires you can load Epplus. But you aren't loading it's requirements. As a result you'll -still- get a FileLoadException.

Now you can of course embed the Epplus.dll library in Library B and load it from a resource stream. The problem with this approach is that any time the Epplus library changes, you'll need to recompile your Library B and you're still not getting all of Epplus's references anyway.

Nuget of course would take care of all this... but would require you to ship your executable code with a direct reference to Epplus which defeats the whole concept of separation of concerns. Worse, if you have ten different implementation libraries, your executable will need to reference all of them even if the user never uses them.

What I have tried:

Embedding the reference library inside library B and loading it during the AssemblyResolve event.

解决方案

GitHub - Fody/Costura: Embed references as resources[^]
NuGet Gallery | Costura.Fody 1.6.2[^]


这篇关于库中的嵌入式引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆