简体   繁体   中英

How can you make a C++/CLI DLL resolve a dependency on managed assemblies (DLLs), without using the GAC?

We currently build an ODBC driver as 4 DLLs:

  1. A DLL implementing the ODBC (C) API, mostly implemented in C++, with some 'glue' code written in C++/CLI, used to interact with #2, #3, & #4

  2. A DLL containing a managed assembly (written in C#) which defines the 'base' interfaces used for #1 & #4 to talk to each other.

  3. Another DLL containing a managed assembly that depends on #2, and defines some extensions to the classes in #2
  4. Yet another DLL containing a managed assembly, which contains the 'business logic' for the driver, which depends on #2 & #3

To deploy the driver, we configure a DSN to point to #1, and put #2, #3 & #4 into the GAC.

We have a customer who wants to avoid the GAC entirely. I know that putting #2, #3, and #4 into the same directory as the application which loads #1 'works', but that's not a good solution, because many different applications might use the driver.

How can we set it up so that the dependencies can be resolved without the GAC? I've tried creating manifest files (based on https://docs.microsoft.com/en-us/windows/win32/sbscs/assembly-manifests ), but that didn't seem to work (EEFileLoadException exception gets thrown because it can't find the managed assemblies, same thing that happens as soon as I remove the dependencies from the GAC). I put the manifest files, and all of the.DLL's into the same directory.

I couldn't find any good documentation/examples for this case with some (perhaps not enough) googling.

I'm not sure that I entirely understand your question, but I'll try to answer:

While trying to solve this, we should remember the following:

  1. Fusion doesn't kick in (and thus dependency resolution), until you are in a stack frame, where the first appearance of the unresolved type is located.
  2. We can assume that the CLR is already loaded in the host process, and we have at least one Appdomain. ( Otherwise, you have to think about both scenarios - especially being consumed by a process, which doesn't load CLR by default. What do you want to do in such case? Load CLR yourself? Implicitly? Explicitly? If so, how do you configure your Appdomain? Where is your App Root? What are your probing paths? )

Given these two points, you can subscribe to AppDomain.AssemblyResolve Event . But you should refactor your code in such a manner, so fusion doesn't try to resolve your assemblies before you've managed to subscribe. In the handler, handle only the events in which YOUR assemblies are being resolved, and load them from any location you want - for example, from the same path, in which your native library resides.

Additional reading:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM