Our application uses a fairly recent protobuf-net(version 2.0.0.668) and I am trying to integrate to another system that has a client library using an older version of protobuf-net(version 1.0.0.282). Is it possible to use the libraries side by side using an assembly resolver on the same windows service? I understand that there are breaking changes between these versions in terms of the serializer as well as google having separate protobuf protocol breaking changes between the versions.
I tried to use the assembly resolver approach because we wanted to reduce the overhead of calling to this client library by going out of process and making a call over the wire for each client call. I wanted to make it work side by side.
Even when the assembly resolver is in place(details below). And I call an Assembly.Load on the library that needs the old protobuf it seems to get the new version. Even when I have no binding redirects on. Also I did specifically specify in the project file to disable auto generation of binding redirects.
Why is the completely isolated project defaulting to the new version of protobuf even when I specified a specific version reference to the project to use version 1.0.0.282? The end result is that I cannot successfully serialize protobuf messages on the library that requires version 1.0.0.282 version of the protobuf.net.
I've got constraints of not using GAC and also to not to create another service to wrap the call to the older versioned client library on another service making it a very expensive call by going out of process.
My project structure is as follows
Solution |_WindowsService - referencing DLL LibraryA and DLLLibraryB |_DLL_LibraryA - referencing protobuf 2.0.0.668 and DLL_LibraryB |_DLL_LibraryB - referencing protobuf 1.0.0.282 and DLL_ThirdpartyClient
DLL_LibraryA and DLL_LibraryB project are setup with a reference to protobuf.net to use specific versions and to not copy local.
I created a build event on the WindowsService project to file copy protobuf-net files in bin->ThirdParty->protobuf-net->{version} folders to be discovered by the assembly loader whend the appdomain resolveassembly event is triggered.
Even when I completely isolate the assembly and set the project configuration to disable auto generation of binding redirects (Disable automatic binding redirects). My assembly loader only gets called for version 2.0.0.668.
One thing of interest though is that our solution makes use of MEF for composition and dependency injection. I wonder if it has any effect. Also based on the structure of my solution the DLL_LibraryA has a dependency on protobuf-net 2.0.0.668 and inderectly to protobuf-net 1.0.0.282 via the dependency of DLL_LibraryB. What does the clr do in this case? Is there a way to do this successfully without going out of process? Is it because of the mix of dependencies that the CLR always decided to make me load the newest version?
Any information would be much appreciated.
Details here:
Create a version resolver - Using assembly resolver Using Side-by-Side assemblies to load the x64 or x32 version of a DLL
public static Assembly VersionResolver(object sender, ResolveEventArgs args){ var assemblyName = new AssemblyName(args.Name); var name = assemblyName.Name; var version = assemblyName.Version.ToString(); string versionedAssemblyProbingPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, string.Format(@"{0}\{1}\{2}", THIRD_PARTY_FOLDER, name, version), string.Format("{0}.dll", name));Assembly returnAssembly = null; if (File.Exists(versionedAssemblyProbingPath)) { returnAssembly = Assembly.LoadFile(versionedAssemblyProbingPath); } else { //Log here and return null } return returnAssembly; }
Invoke resolver in windows service program -
static Program() { AppDomain.CurrentDomain.AssemblyResolve += VersionResolver; }