Dependency Injection while dynamic assembly loading - c#

i have a winforms applicatoin that has a lot of implementations of IOrderDataLoader. Other teams are starting to build their own new implementations of IOrderDataLoader. So we switched our app to look in a directories of Dlls and load all classes that implement IOrderDataLoader using reflection. This way other groups can deploy their dlls on their own and the main app loads them on demand.
The problem is one of the implementations that we have as an internal project that we are trying to move out into its own deployment has a number of dependencies. How i do i break this out and load it up with all the dependencies? All the other data loader have empty constructors so i simply just loop . .

Try looking at the Managed Extensibility Framework. It is a framework for doing what you've already done, and supports dependency injection in the style you request.

Related

Reference multiple versions of the same DLL

I have a project which needs to indirectly use three different versions of a third-party library. These versions are incompatible with each other, so I can't use a binding redirect - it has to be the exact .dll file. (The libraries are Spire.Doc, Spire.XLS & Spire.PDF; the Spire.PDF DLL is referenced by all three)
I have separated the three components into individual wrapper projects, and created classes which wrap direct references to anything in the libraries. However, this doesn't solve my issue: the 'consuming' project still has to copy all of the libraries to the bin folder in order to run. The build process doesn't know which version to copy, and so just copies the latest one. This gives me runtime exceptions due to the wrong DLL being present.
What I've considered/tried:
Adding a binding redirect to a specific version (runtime exception because the exact version of the library is not found)
Using a post-build step to merge the wrapper projects (again a runtime exception complaining about the absence of the library DLL)
Creating separate console applications for each part of the application, then invoking them in a separate - this is a complicated last resort that I'd really rather not do!
I have read that extern alias might be able to help - but as far as I can tell, you can only distinguish between assemblies with different names. The Spire.PDF library has the same name in each project (and the same signed public token).
How can I use these three separate versions of the library independently in the same solution?
Edit:
This issue is slightly different to the suggested duplicate because I don't have the ability to change any code in the dependent libraries. Spire.Doc relies on a different version of Spire.PDF to Spire.XLS
In your consuming project (Project A), create a common interface (ISpiroPdfAlex) that encompasses all the functionality that the 3 versions of your external assembly provides (and you use). You cannot reference anything in Project A from these wrappers in any way, otherwise you'd create a dependency, which is what you're trying to avoid.
Have all 3 wrapper projects import Project A and implement ISpiroPdfAlex. This will give you the ability to call each of the 3 different versions through the same API.
After this, create a subfolder under Project A for each of the versions (so 3 subfolders total) - since Project A has no reference to any of the external assemblies, it cannot load them by itself - you'll have to manually load them when you need the right version. Since your external DLLs may have dependencies with the same name, they cannot all be in the same folder (as you wrote), this is why you need the subfolders.
At run-time when you need one of these versions, you can call Assembly.LoadFile to load a specific version of your assembly from the specified folder and then you can either use Activator.CreateInstance or dependency injection to create an instance of a class that implements your interface. Once you have the instance, you're free to call any of the functions and you'll get version-dependent behavior.
Edit:
OP mentioned in a comment that it's not his code that has the dependency on different versions of the PDF library but the other 3rd-party Spire libraries that his code depends on.
In this case, the 3rd-party code cannot be modified to support dynamic loading of assemblies and they already have a binary dependency. It's not possible to load different versions of the "same" assembly into the same process, especially that you mentioned that these versions are not even backward-compatible with each other.
The only solution I can think of in this situation is to break out all dependent functionality into separate console applications (one for each different version) and call those separate .exe-s through the command-line.
To pass information, you can either pass data directly on the command-line or through stdin. Alternatively, you can just pass the name of a temporary file that has all data necessary to do some processing. To get return data back from the console process, you can either read its stdout or use the same / different file.
This way your main process never loads any of these assemblies and has no dependency on them - each console application has a dependency on just one version so there's no collision.

How to resolve NuGet dependency hell

I develop a library with some functional named CompanyName.SDK which must be integrated in company project CompanyName.SomeSolution
CompanyName.SDK.dll must be deployed via NuGet package.
And CompanyName.SDK package has a dependency on 3rd party NuGet packages. For good example, let's take Unity. Current dependency is on v3.5.1405-prerelease of Unity.
CompanyName.SomeSolution.Project1 depends on Unity v2.1.505.2.
CompanyName.SomeSolution.Project2 depends on Unity v3.0.1304.1.
Integrating CompanyName.SDK into this solution adds dependency on Unity v3.5.1405-prerelease.
Let's take that CompanyName.SomeSolution has one runnable output project CompanyName.SomeSolution.Application that depends on two above and on CompanyName.SDK
And here problems begin. All Unity assemblies has equal names in all packages without version specifier. And in the target folder it will be only one version of Unity assemblies: v3.5.1405-prerelease via bindingRedirect in app.config.
How can code in Project1, Project2 and SDK use exactly needed versions of dependent packages they were coded, compiled and tested with?
NOTE1: Unity is just an example, real situation is 10 times worse with 3rdparty modules dependent on another 3rdparty modules which in turn has 3-4 versions simultaneously.
NOTE2: I cannot upgrade all packages to their latest versions because there are packages that have dependency not-on-latest-version of another packages.
NOTE3: Suppose dependent packages has breaking changes between versions. It is the real problem why I'm asking this question.
NOTE4: I know about question about conflicts between different versions of the same dependent assembly but answers there does not solve the root of a problem - they just hide it.
NOTE5: Where the hell is that promised "DLL Hell" problem solution? It is just reappearing from another position.
NOTE6: If you think that using GAC is somehow an option then write step-by-step guide please or give me some link.
Unity package isn't a good example because you should use it only in one place called Composition Root. And Composition Root should be as close as it can be to application entry point. In your example it is CompanyName.SomeSolution.Application
Apart from that, where I work now, exactly the same problem appears. And what I see, the problem is often introduced by cross-cutting concerns like logging. The solution you can apply is to convert your third-party dependencies to first-party dependencies. You can do that by introducing abstractions for that concepts. Actually, doing this have other benefits like:
more maintainable code
better testability
get rid of unwanted dependency (every client of CompanyName.SDK really needs the Unity dependency?)
So, let's take for an example imaginary .NET Logging library:
CompanyName.SDK.dll depends on .NET Logging 3.0
CompanyName.SomeSolution.Project1 depends on .NET Logging 2.0
CompanyName.SomeSolution.Project2 depends on .NET Logging 1.0
There are breaking changes between versions of .NET Logging.
You can create your own first-party dependency by introducing ILogger interface:
public interface ILogger
{
void LogWarning();
void LogError();
void LogInfo();
}
CompanyName.SomeSolution.Project1 and CompanyName.SomeSolution.Project2 should use ILogger interface. They are dependent on ILogger interface first-party dependency. Now you keep that .NET Logging library behind one place and it's easy to perform update because you have to do it in one place. Also breaking changes between versions are no longer a problem, because one version of .NET Logging library is used.
The actual implementation of ILogger interface should be in different assembly and it should be only place where you reference .NET Logging library.
In CompanyName.SomeSolution.Application in place where you compose your application you should now map ILogger abstraction to concrete implementation.
We are using that approach and we are also using NuGet for distribute our abstractions and our implementations. Unfortunately, issues with versions can appear with your own packages. To avoid that issues apply Semantic Versioning in packages you deploy via NuGet for your company. If something change in in your code base that is distributed via NuGet you should change in all of the packages that are distributed via NuGet. For example we have in our local NuGet server :
DomainModel
Services.Implementation.SomeFancyMessagingLibrary (that references DomainModel and SomeFancyMessagingLibrary)
and more...
Version between this packages are synchronized, if version is changed in DomainModel, the same version is in Services.Implementation.SomeFancyMessagingLibrary. If our applications needs update of our internal packages all dependencies are updated to the same version.
You can work at post-compilation assembly level to solve this issue with...
Option 1
You could try merging the assemblies with ILMerge
ilmerge /target:winexe /out:SelfContainedProgram.exe Program.exe ClassLibrary1.dll ClassLibrary2.dll
The result will be an assembly that is the sum of your project and its required dependencies. This comes with some drawbacks, like sacrificing mono support and losing assembly identities (name, version, culture etc.), so this is best when all the assemblies to merge are built by you.
So here comes...
Option 2
You can instead embed the dependencies as resources within your projects as described in this article. Here is the relevant part:
At run-time, the CLR won’t be able to find the dependent DLL
assemblies, which is a problem. To fix this, when your application
initializes, register a callback method with the AppDomain’s
ResolveAssembly event. The code should look something like this:
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
String resourceName = "AssemblyLoadingAndReflection." +
new AssemblyName(args.Name).Name + ".dll";
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) {
Byte[] assemblyData = new Byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
};
Now, the first time a thread calls a method that references a type in
a dependent DLL file, the AssemblyResolve event will be raised and the
callback code shown above will find the embedded DLL resource desired
and load it by calling an overload of Assembly’s Load method that
takes a Byte[] as an argument.
I think this is the option i would use if I were in your shoes, sacrificing some initial startup time.
Update
Have a look here. You could also try using those <probing> tags in each project's app.config to define a custom sub-folder to look in when the CLR searches for assemblies.

Universal Apps with IoC: Dependency management/isolation

I'm a huge fan of using Unity for .NET applications to keep code module and dependencies "manageable" in large code-bases. I've used it for years with .NET by dropping assemblies into the main program's program directory and re-configuring an IoC configuration file (usually the .exe.config file), injecting new behaviour into a program without needing to re-compile the main program.
However, I have started my foray into writing universal apps for Windows Store and more importantly, Windows IoT - however because these apps are "packaged up" during compilation, I'm finding it difficult to understand how best to continue doing this.
One possible option would be to compile the "modules" (PCL/Universal class libraries) and include them (and their dependencies) as "Content" files within the Universal app, then use reflection to load types from these assemblies during the start-up of the program via reflection.
Another option would be to include all modules and their dependencies into the main program's project references before compilation but using "poor man's dependency injection to hard code the registrations and resolutions", but this feels really wrong to me - I'd ideally like to keep the separation of dependencies if at all possible?
Any ideas...?
PS. I'm not tied to Unity in any way, if there is another IoC library that does it better on this platform then fine - but Unity is what I already know and love!
I do this using Castle Windsor. You can probably use the same approach with Unity:
Limit references only to when an assembly needs a type defined in
another assembly
Define a class (or classes depending on how you want to organize) for IoC configuration in each assembly by implementing IWindsorInstaller and configure DI using the fluent API inside the implemented Install method.
Define a container instance inside your app root
At application start, use reflection to find all types implementing
IWindsorInstaller in the bin folder and run their Install method,
passing in the container instance
This way you can keep your dependencies separate, and you don't have to worry about adding extra references or adding .dlls as content files.

.net Dynamic Reference but still have intellisense

Our team works on Modules that have dependencies to different assemblies. E.g. We have a EmailClient Module that uses one set to assemblies for one particular build and another set of completely different assemblies for another build. That's because depending on the customer we integrated to different backends.
We want to keep one source tree for the EmailClient and make sure the "Latest" version always works for all customers. Our challenge here, is to not distribute unnecessary assemblies to one set of customers. As they get picky and ask what all these other files are for.
This is causing the following error and is very difficult to catch in one place:
System.IO.FileNotFoundException: Could not load file or assembly.
Does .Net provide such a feature where we can add reference to all sorts of assemblies, but not distribute some of them?
You should look at a plugin architecture like Managed Extensibility Framework (MEF) http://msdn.microsoft.com/en-us/library/dd460648.aspx
This way you can expand your current application without creating dependencies to assemblies.
Even if you're not planning to implement MEF. It will gives ideas and new ways to think, about how to implement it your own.

C# .NET 4.0 Forms plugins manager

I'm a bit lost with MEF, MAF, Unity ...
This question is about architecture of Winform application.
I've got a main project which contains a Main form and some other forms;
Because i want to include modularity, i'm thinking of using a Plugin System.
What I would like to do is opening each Plugin Dll when the Main Application is opened to reference each with button, toolbar ...
Then i would like to dispose them until they are called.
But i don't want all the plugins to be kept in memory.. just to got a good architecture model.
So first about .NET :
Does dotNet keep only a reference to the dll plugins in memory or all the plugin code ?
I'm thinking of using MEF with LAZY collection of Import, but i need to instantiate them first to get my buttons informations. So second question
If i set the Import Collection to null and lauch the compose() function again, the plugins will be load or wait until call to be load (lazy) ?
Then i would like to dispose them until they are called.
Instead of inspecting imported objects and then throwing them away, you should inspect the import metadata. You can get this metadata by importing Lazy<IFoo,IFooMetadata> or Lazy<IFoo,Dictionary<string,object>>. You can add this metadata to exports with the ExportMetadata attribute.
So first about .NET : Does dotNet keep only a reference to the dll plugins in memory or all the plugin code ?
Once an assembly is loaded it remains in memory, unless you unload the whole AppDomain.
Also, there are no out-of-the-box implementations of ComposablePartCatalog in .NET 4.0 which can be queried without loading the corresponding assembly. But in theory something like that could be done if you store the metadata somewhere outside the assembly. There is a sample of such an implementation in the MEF code on codeplex.
I'm thinking of using MEF with LAZY collection of Import
Using lazy imports will not necessarily prevent assemblies from being loaded. If you have a reference to a Lazy<IFoo> object, then at least the assembly containing IFoo has to be loaded. And as I explained above, the assembly containing the exported IFoo implementation will also have been loaded at that point.
Using Lazy will only postpone the invocation of some constructors, hopefully resulting in faster start-up of your application.

Categories