views:

276

answers:

2

Is it possible to write an assembly which dynamically generates/emits a new class and patches itself to include the new class?

How?

+1  A: 

The best way to do this is to use dependency injection / inversion of control or even a simple service locater.

Your new assembly would create a new concrete implementation and register that instead of the old implementation.

I'm certain that anything more exotic would be a terrible hack indeed.

Luke Schafer
Could you explain this more? Basically, I have an assembly to deploy, and the class that used to be hand-coded in it is now generated dynamically. I want this class in the original assembly, but I wanted it dynamically generated by the assembly, rather than hand-coded by me. Is that possible?
Triynko
something like autofac or windsor can be used to register concrete implementations of classes that are then injected from or retreived from the container. It's a simple way to organise your implementations (and that's a terribly simple explaination).If you re-architect your software such that the original implementation is drawn from a container or service locator, then you can easily override that with a custom implementation (as long as the original isn't sealed)
Luke Schafer
I don't think that's what I'm looking for. The data classes already exist, and I was just extending the dll to have auto-generated functions which instantiate each data class, and can be registered as CLR functions in SQL Server. This requires the dynamically generated code to be included in the original dll. So far, the solution I'm using is to just use ILMerge as a post-emit step, and that works fine.
Triynko
+1  A: 

I asked this question another way here: http://stackoverflow.com/questions/885128/using-assemblybuilder-how-can-i-make-all-or-any-of-the-referenced-assemblies-emb

Patching the existing dll with the dynamically generated code would result in the same thing as embedding the original dll in the dynamically generated code -- a single assembly with the contents of both.

It seems that one way or another, to eliminate dependencies and pack the contents of multiple assemblies into one, the ILMerge utility is the most elegant solution.

The only problem with it is that the types generated in the merged dll are incompatible with the same types in both of the original dlls. If the original DLL, for example, emits a new assembly, merges it with itself, and loads the new assembly... it cannot use its own types to refer to things in the new assembly which correspond to the same type in either of the original assemblies.

In other words: Class A in [dll_generator] references [dll_1]. Class A generates [dll_2], which is based on and of course also references [dll_1]. Class A calls ILMerge to combine [dll_2] with its dependency [dll_1] to produce [dll_merged]. None of the types in [dll_merged] are compatible with any of their original types in [dll_1] and [dll_2], so if class A loads [dll_merged] and tries to do anything with it involving literal type names from its original reference to [dll_1], it fails, because the types are incompatible. The only way class A can work with types in [dll_merged] is to load them by name and work entirely with 'Type' objects and reflection -- or dynamically compile source code against the new [dll_merged].

Triynko