0

I am trying to code an application in C#.NET Core that can be extended using MEF. Currently, I am able to do that without any issues with libraries, that have no dependencies or have the same dependencies as the host app (so dependencies are already loaded). But, if I want to use a library with a NuGet reference, that is not used by the main app, the loading of this library fails on that reference.

How can I force the main app to load the missing NuGet dependency, if it tries to load an assembly with such reference? It seems to me as a pretty common use case, but I am lost here and cannot find a way out. Thanks.

For reference, I am posting the portion of the code.

[ImportMany]
private IEnumerable<Lazy<IService, IServiceMetadata>> _asrServices;

...

var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(Path.Combine(Directory.GetCurrentDirectory(), "Services")));          
CompositionContainer _container = new CompositionContainer(catalog);

...

foreach (Lazy<IService, IServiceMetadata> _service in _asrServices)
{
   var _serviceInstance = _service.Value // here the loading fails
}

Jiri

  • I think maybe it’s because you put those assemblies in a different directory? Either move then to the same directory as the main exe or use something like: https://stackoverflow.com/questions/5260404/resolve-assembly-references-from-another-folder – Dave M Mar 15 '19 at 02:27
  • Yeas and no. I always copy all DLL files that are produced by a successful build of the plugin. So there is no issue with direct references (e.g. directly referenced libraries without NuGet). I have issues only with NuGet packages. These libraries are not part of the build output, so I cannot copy them to the main app folder. So the main app is able to resolve its own NuGet dependencies without copying these DLLs to the output, but it is unable to resolve plugin dependencies. I´ve checked the common NuGet storage, and all the libraries are there. Only the main app is not using them. – Jiří Kubeš Mar 15 '19 at 06:35
  • It can't be yes and no.When you run the applicaion, are the plugin DLLs and their references (the NuGet DLLs) in the same directory as the EXE or not? This has nothing to do with NuGet or MEF. It's simply the framework doesn't know where to look for the referenced DLLs if they are not in the same directory as the currently executing EXE (if you load a DLL from a different directory as the main EXE, the framework won't look in that directory for it's dependencies, it will look in the current directory) – Dave M Mar 15 '19 at 14:48
  • Assuming the plugin is using the new SDK style project file, you need to publish the project, which will copy not only the project's dlls, but also its dependencies, into a single folder. https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-publish?tabs=netcore21 – zivkan Mar 15 '19 at 15:48
  • @Dave: Yes, I understand. The NuGet dependencies are not there, simply because build action doesn´t export these DLL to the output directory. I know how to deal with simple references, and for them, my solution works. The issue I had was with NuGet packages. – Jiří Kubeš Mar 16 '19 at 13:00
  • @zivkan: Thank you, that was it! I´ve tried to publish the project directly from Visual Studio, but it always generated new NuGet package from my project. But publishing from command line gathered all needed DLLs in single folder, so I can handle them accordingly. – Jiří Kubeš Mar 16 '19 at 13:05

1 Answers1

0

.NET currently has two build "systems". One is the original project files, that import Microsoft.Common.props and Microsoft.CSharp.targets (assuming it's a c# project) and lots of XML in between, that has been around ever since .NET was first released, apparently in 2002. Since .NET Core was made generally available in 2016 there has been a new project system generally called SDK projects because the way a *proj file references the build system is though an Sdk element or attribute in the msbuild xml. Although it's off-topic, because there's a common bad assumption, I want to point out that although SDK projects were created for .NET Core, you can target the .NET Framework from SDK projects.

With the original project files, when you build, all the projects references get copied to the output directory. However, with SDK projects, only the project's assembly is copied to output (I'm not sure, but I think even content set to copy to output doesn't actually get copied on build). In order to get everything in a single directory, you should use the dotnet cli's publish command.

So, if you have a build script that builds your project and copies all the plugins somewhere, you should add a dotnet publish step to the script for each plugin using the SDK style project file.

zivkan
  • 12,793
  • 2
  • 34
  • 51