Search code examples
c#interceptorfactory-patternil

Enforcing factory pattern to a specific set of types by replacing their constructor


It it possible, in ANY way (IL hacks included) to automatically "replace" the call to a certain constructor, eg

public void Car(Color color)
{
    this.Color = color;
}

By a factory method, eg

public static Car Create(Color color)
{
    return new Car(color);
}

that returns the original type of a subtype of it?

I would like to archive automatic factories through an interface: Get all Types and replace or at least work around their constructor.

Any thoughts on intercepting and IL hacking are welcome. I tried to add an extension method to all types that implement the interface, but as you know static methods are not working out.


Solution

  • This is a non-trivial task, but if you have to, you can do this with IL Weaving. I have done a similar thing in the past in a test project, while trying to implement a checked exception library. I did not get around to finishing this due to time constraints.

    If you do own the library, then indeed marking the ctor as private will be enough :) but I am guessing that in order to ask, you already exhausted that possibility. Due to this I assume that compile time solutions are not enough. If they are OK, but still you do not want to mark your ctor as private, then check PostSharp I DEFINITELLY recommend it!

    Otherwise, you can use Cecil. With Cecil you will be able to load a library, load types, find methods, and scan for calls to the Car ctor and replace them with a call of your own. This will be a task that will require quite a bit of IL knowledge and is quite involved for a StackOverflow answer.

    If you are launching the application from assembly A and:

    • Car is defined in assembly B and all types required are either in B or referenced by B: unload B, weave your changes in B (in a temporary copy if you do not want to change the original), reload B.
    • Car is defined in assembly B but types required are not in B or A: Same as above, but you during your weave you will have to add references to the assemblies that the required types are in.
    • Car is in A or you need to reference types in A in the factory method: You need to weave the caller assemblies (the assemblies calling the Car ctor).
    • Car is in A and the caller is from A: You can copy the assembly, weave the assembly, close and relaunch from the weaved assembly. Instead of this scenario consider using PostSharp.