Click here to Skip to main content
15,890,995 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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.
Posted

1 solution

 
Share this answer
 
Comments
Eiredrake 22-Jan-18 14:22pm    
So far so good, thank you.

Looks like it works right out of the box in the regular .net framework.

Having some issues getting it going with .net standard.

But hey it's a starting point. Awesome! Thanks!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900