Fabrikmuster - Erzeuger registrieren



  • Ich möchte in C# eine Fabrik anlegen.
    Da unbekannt ist, welche Objekte auftreten können, soll jede Klasse die einer Assembly hinzugefügt wird, einen Erzeuger in der Fabrik registrieren.

    In C++ habe ich dafür Aufrufe dieser Art erzeugt:

    namespace
    {
    	static		FabrikBasis * KB_DirCreator(){return new KB_Dir;}	
    	static bool KB_Dirregistred =	Factory().Register("Dir",KB_DirCreator);
    }
    

    So war zur Laufzeit jedes, im Projekt verwendete Objekt in der Fabrik bekannt. Mir fehlt für C# jedoch der Ansatz diesen "C++ Trick" in C# umzusetzen, da ich nicht weiß wie ich eine Initialisierung in einer Unit erzwingen kann ohne das in der Fabrik oder anderstwo gesammelt die Registrierung manuell vorgenommen wird.

    Ich würde mich freuen, wenn mir jemand z.B. ein paar Stichworte für die weitere Suche geben könnte.



  • In Java gibts statische Initializer und Konstruktoren, hat C# nicht etwas äquivalentes?



  • Meinst Du sowas ?

    static foo()
    {
       static foo()
       {
         // Registriere Erzeuger
       }
    }
    

    static foo() wird AFAIK aber nur ausgeführt, wenn ich den Typ foo auch irgendwo anspreche. Ich müsste dann an einer Stelle alle Typen sammeln - das wollte ich gerne umgehen in dem jede Klasse sich - mehr oder weniger - von alleine Registriert.



  • Die derzeitige Lösung schaut so aus:

    internal interface IAbfrageObjekte
            {}
    
            public abstract class Basis : IAbfrageObjekte
    {}
    
    class Text : Basis
            {
    
                internal static Basis Create()
                {
                    return new Text();
                }
                internal override void Register()
                {
                    Fabrik.reg(FeldTypen.Text, Create);
                }
    
    public delegate Basis Creator();
    
            public static class Fabrik
            {
                public  static void fakeinit_Fabrik(){}
    
                static System.Collections.Generic.Dictionary<FeldTypen, Creator> objects;
                static Fabrik()
                {
                    objects = new System.Collections.Generic.Dictionary<FeldTypen, Creator>();
                    Assembly asm = Assembly.GetExecutingAssembly();
    
                    foreach (Type typ in asm.GetTypes())
                    {
    
                        if (typ.IsAbstract || typ.GetInterface("IAbfrageObjekte") == null)
                            continue;
    
                        Basis b = (Basis)asm.CreateInstance(typ.FullName);
                        b.Register();
    
                    }
                }
    
                public static void reg(FeldTypen typ, Creator c)
                {
                    objects.Add(typ, c);
                }
    
            }
    

    Es gefällt mir aber nicht.

    a) ich hab keine Erfahrung mit Reflections
    b) ich muss mühsig alle Typen untersuchen ob diese zur Fabrik gehören
    c) ich muss davon eine Instanz erstellen um die Reg Methode der eigentlichen Klasse aufzurufen.

    Der Aufwand gegenüber der alten C++ Lösung ist enorm. Ich hoffe das es eine bessere Möglichkeit gibt, sonst muss ich doch jede einzelne Klasse manuell ansprechen was bei der Anzahl der zu erwartenden Klassen Fehleranfällig wird :o(


Anmelden zum Antworten