Gilthans
Gilthans

Reputation: 1726

Static initialization BEFORE main

I have a piece of software where there is a central abstract Factory method responsible for opening files. At first, the factory knew about all the file-types it can open and the corresponding objects it creates (every file-type has a different handler), but as time grew it became impractical: firstly, it was undesirable to fiddle with the factory class when handling new file-types; secondly, some of the concrete file handlers existed in separate DLLs, making them inaccessible from the factory! (The file handlers sometimes require the factory to handle files who only index paths to other files, therefore they must know the factory; if the factory knew them, the dependency would be cyclic)

The solution we came up with is for every new object type to 'register' itself with the factory, so that once the factory method is created, it will test the registered object types to see which one is the most suitable one and create it.

The largest problem is: when do these objects register themselves to the factory? Ideally, it would happen once before any call to the factory. However, since in C# you can't count on static c'tors to be called before accessing the type, I don't know how this can be done. Our current solution is to perform a dll-wide Initialize method which registers the object types with the factory, but this is obviously a hack which I dislike.

Is there some design pattern we're missing? A different way to handle this? It is important to note that the file handlers which need to register to the factory are in separate DLLs which MUST reference the factory.

Upvotes: 3

Views: 196

Answers (4)

Gilthans
Gilthans

Reputation: 1726

The best solution I've come up with (when discussing it with Scott Chamberlain) is to either use Unity, or use attributes to tag all the file-type handlers, and then load them all on the factory's static c'tor via reflection. So for example:

[FileHandler]
public class TxtFileHandler : FileHandlerBase
{
...
}

And then load all the classes marked with FileHandler using reflection, and registering them, for example by using a property to map them to a file extension.

Upvotes: 0

Igor
Igor

Reputation: 15893

We resorted to loading all types from all assemblies in the execution location, scanning them for a static method marked with a special attribute and invoking these methods - the reflection option that Scott Chamberlain mentioned.

Upvotes: 1

Scott Chamberlain
Scott Chamberlain

Reputation: 127593

I would not consider a dll wide function to initialize a dll to be a hack at all. That is exactly what DllMain does for native DLL's.

Create a function in each dll that initializes it on load and have it register with the factory. Then call that function as the first function of your DLL loading code in your main app.


However a even better way to do it is use some form of Dependency Injection library, for example Unity, that can handle the registration of types in DLLs to factories for you automatically via configuration files or via reflection.

Upvotes: 1

Kirill Bestemyanov
Kirill Bestemyanov

Reputation: 11964

It seems that you have some problems with design of your application. There is some techniques to brake cyclic dependencies like yours. Usually programmers use inversion of control for this. In this case you can use in your "factory" class interface of handler instead of concrete realization. Interface should be defined in same dll with factory or in another "core" dll, that will be referenced from both your dlls.

Upvotes: 1

Related Questions