Reference Assembly for Bix Mixers
In building the Bix CecilMixer, which uses Mono.Cecil to perform the post-compile mixing (a.k.a. code weaving) step, I've found myself making heavy use of ildasm to examine compiled assemblies. Up until now, I've mostly been creating code similar to what I want on an ad-hoc basis, compiling it, and then disassembling it. I'm still in very early development, and this is already starting to become a lot of overhead.
It's time to formalize and improve this strategy.
I've already created a test mixer target assembly that I'm using to test mixing functionality, so I have a well-known starting point for mixing. I also know how a C# version of the mixed code should look (after all, I've been creating small, ad-hoc pieces in C# and compiling as needed); the next logical step is to create and maintain a reference version of the post-mixed assembly. This will allow me to "save" my work, so to speak, and it will allow the reference assembly to become part of the unit testing process. I might even drop other unit tests in favor of a single deep assembly comparison test. (I haven't made that decision yet, but don't be surprised if you see it happen.)
So far, this is natural evolutionary step devoid of any hard decisions. It does present a task in performing the deep structure comparison that is arduous, if not necessarily difficult. It's a lot of up-front work, and I see the possibility of needing to tinker with it a lot as the code base evolves. The basic idea is straightforward, though, in that the two assemblies have different filenames but should contain the same namespaces, type names, and everything else. After mixing the test target, a deep structure comparison should show only a difference in module names (because module names correspond to filenames). To reference both projects from the test project, I simply have to give one of the references, the reference assembly in this case, an alias. (Sorry for causing parsing difficulties with the two different uses of "reference" in that last sentence.)
Now: should I test the generated IL code along with the structure?
It seems like I won't know the "right" answer to this for some time. Because I will generate the code based on disassembly of the compiled referenced code (minus extra nop instructions), all I will need to do for initial, simplistic testing is to compare instructions with nop ignored. Up front, I plan to do this, but I am certain that this will too easily break. For example, compiling in Release mode might cause enough difference to break the code. Using the mono compiler might break it. Upgrading the .NET SDK might break it.
For now, I'll be taking the pragmatic direction of writing IL comparison tests that are usable for me during my current development but that will be easy to comment out/remove/put #ifdef
around if needed. I assume that I will eventually need to put time into solving this more generally, but I'll not be shaving that yak today.