views:

319

answers:

2

I am merging several .NET assemblies using ILMerge including some 3rd party assemblies. Since doing so, I've experienced several errors that all boil down to the fact that type definitions are tied to the assembly they are defined in.

A simple example is the log4net config section definition in my App.config. It uses type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" which will not work since the log4net assembly does not exist once it has been merged into my merged assembly. Not a big deal though, I change the assembly name to my merged assembly and it works fine.

A slightly more complicated example is binary serialized types. My system uses binary serialization to send certain objects between processes. All of the serializable objects are defined in a common assembly that all of the other projects reference. I was using the default binary serialization, but it started failing when deserializing the objects with the error stating that it could not find the merged assembly that serialized the object. Again, not a big deal, I implemented a custom SerializationBinder that looks for the type in any loaded assembly, not just the one given.

The previous example got more complicated when the serialized type reference other serializable types. I've continued to run into more and more problems that are getting increasingly difficult to deal with.

The point I'm trying to get at here is that the .NET type system and ILMerge don't appear to play well together. Does anyone have any experience with how they have solved this problem? Is it possible to tell the .NET runtime that I don't care what assembly the type says it should be in, just look for it anywhere?

NOTE: Please do not reply asking why I'm merging assemblies, that is not the point of this question.

A: 

Welcome to perils of strings and (physical-location) strings in code..

All tools of that kind have similar problems and they better be smart, as many devs and designers of runtime features such as binding and serialisation didn't really envisage it but they sure pushed ILMerge as a 'smart' tool. It's so smart it can't even prune types.

Note that versioning also comes into play here, and configuration, .* and stars-in-their-eyes, and version independence from Redmond does not help either.

You will keep hitting trouble with thirdy party bits for sure. And believe me, I know you need the merging, as some pathetic small number of types can take ages for MS JIT to kick in for large apps (and nope, I don't want NGEN or optimised 3.5SP1 loading that's even slower than before due to System.Core or heaven-forbid WPF bloat ).

Best option, imho, at least on a large scale, is to get a decent commercial tool that scans and handles this (ie. from the existing pain and obfuscation experience out there). In the long run, you might end up instrumenting existing IL code if you don't have the sources.

[ Then there was a INotifyPropertyChanged string invention that so solved the global warming problem - Designed by Casio-Calc Inventors ]

rama-jka toti
+2  A: 

Yes, there is a solution to this problem: Build modules instead of assemblies!

Compilers for .net have an option (/target:module for C# and VB) that builds a module instead of an assembly. Multiple modules can then be passed to the compiler and used to build the final assembly.

Of course, this all assumes that you've got the source to those 3rd party assemblies. If you can't get that, perhaps a .netmodule version of the 3rd party assembly can be procured from the 3rd party?

If that won't work, you've still got one last option. Obviously you're already disassembling a 3rd party assembly into IL. Strip out the assembly information from that IL file and use "ilasm /dll" to build a .netmodule which you should now be able to use just like any other .netmodule!

By using modules instead of assemblies you shouldn't have any more assembly-based issues.

True, we've solved your problem with ILMerge by not using ILMerge anymore, but isn't that really the best solution?

Hope it works for you, here's some handy linkage:
.netmodule instead of assembly
ILASM with .netmodules

(And here I was thinking that my experience with .netmodules would never be useful to anyone!)

Task