DLL in mehrere Speicherbereiche laden



  • Hi zusammen,

    der Titel ist etwas obskur, aber ich habe ein Problem und ich bin mir nicht sicher, wie ich es am Besten löse. Folgende - vereinfacht dargestellte - Situation:
    Library.dll -> Hat eine öffentliche Klasse "LibrarySettings" mit einem statischen string-member "DbTableName".
    FooPlugin.dll -> Verweist auf Library.dll und schreibt/liest das string-member "LibrarySettings.DbTableName"
    BarPlugin.dll -> Verweist auf Library.dll und schreibt/liest das string-member "LibrarySettings.DbTableName"

    Die Property wird an diversen Stellen in der Library.dll verwendet und abhängig vom Wert wird eben aus verschiedenen, gleich aufgebauten, Tabellen gelesen. Alle drei DLLs liegen im gleichen Verzeichnis. Somit ist klar, dass sich FooPlugin und BarPlugin gegenseitig die Variable "LibrarySettings.DbTableName" überschreiben. Das ist aber nicht gerade das, was ich brauche. Sowohl FooPlugin als auch BarPlugin sollten ihre eigenen "Versionen" der Library.dll haben, damit sie sich bei der Property nicht in die Quere kommen. Erschwerend kommt hinzu, dass FooPlugin und BarPlugin von einem anderen Programm (AutoCAD) geladen werden. Die naheliegende Frage ist, wie ich das gebacken bekomme. Soll ich AppDomains verwenden? Oder gibt es da was anderes, was ich nicht kenne?

    Wenn man meine Frage aber anders angeht.. dann habe ich mir überlegt, ob ich das Problem nicht in der Library.dll selbst löse, indem ich z.B. sowas mache (vereinfacht und ohne locking):

    namespace Library {
        public class LibrarySettings {
            private static Dictionary<Assembly, string> interalDict;
    
            static LibrarySettings() {
                internalDict = new Dictionary<Assembly, string>();
            }
    
            public static void Set(string dbTableName) {
                if (internalDict.ContainsKey(Assembly.GetCallingAssembly()))
                    internalDict[Assembly.GetCallingAssembly()] = dbTableName;
                else
                    internalDict.Add(Assembly.GetCallingAssembly(), dbTableName);
            }
    
            public static string Get() {
                if (internalDict.Contains(Assembly.GetCallingAssembly()))
                    return internalDict[Assembly.GetCallingAssembly()];
                else
                    return null;
            }
        }
    }
    

    Man muss das natürlich nicht über GetCallingAssembly machen, sondern kann auch noch einen zusätzlichen Parameter "Assembly asm" in die Funktionen einbauen, um es zu flexibilisieren.
    Was meint ihr? 🙂

    Danke im Voraus

    GPC



  • Für mich liest sich das so, dass Du einfach nur zwei oder mehr Objekte von LibrarySettings benötigst und ein Singleton hier fehl am Platz ist.



  • Ja, das wäre auch eine Möglichkeit, design-mäßig die sauberste. Aber auch eine, die ich eher vermeiden möchte, denn das würde sehr viele Änderungen in diversen Assemblys nach sich ziehen 🙂 Außerdem ist diese Konstellation mit mehreren Assemblys, die auf Library.dll zugreifen, auch ein Einzelfall.



  • Kannst du nicht auf die Library.dll verzichten und die DbTableNames in den app.settings der jeweiligen Dll hinterlegen? Dann sparst du dir zum einen die Extra-Dll und zum anderen kannst du es problemlos pro Dll neu konfigurieren.



  • Firefighter schrieb:

    Kannst du nicht auf die Library.dll verzichten und die DbTableNames in den app.settings der jeweiligen Dll hinterlegen? Dann sparst du dir zum einen die Extra-Dll und zum anderen kannst du es problemlos pro Dll neu konfigurieren.

    Geht leider nicht, da ich viel Funktionalität aus Library.dll brauche - und dort auch der Code drin ist, der DbTableName tatsächlich benutzt, um aus einer konkreten Tabelle zu lesen. Hab mich da wohl etwas unpräzise ausgedrückt 😢

    Inzwischen habe ich mal mit AppDomain herumexperimentiert und ich muss sagen, dass ich grandios scheitere 😃 Von wegen "easy way to separate execution contexts".. pfff. Hat damit mal jemand was gemacht? Ich mein, das gibt's doch nicht, dass man in .NET keine separaten Speicherbereiche haben kann, in die man Assemblies reinlädt.
    Unter Win32 gibt's das ja praktisch ewig 😕



  • GPC schrieb:

    Firefighter schrieb:

    Kannst du nicht auf die Library.dll verzichten und die DbTableNames in den app.settings der jeweiligen Dll hinterlegen? Dann sparst du dir zum einen die Extra-Dll und zum anderen kannst du es problemlos pro Dll neu konfigurieren.

    Geht leider nicht, da ich viel Funktionalität aus Library.dll brauche - und dort auch der Code drin ist, der DbTableName tatsächlich benutzt, um aus einer konkreten Tabelle zu lesen. Hab mich da wohl etwas unpräzise ausgedrückt 😢

    Inzwischen habe ich mal mit AppDomain herumexperimentiert und ich muss sagen, dass ich grandios scheitere 😃 Von wegen "easy way to separate execution contexts".. pfff. Hat damit mal jemand was gemacht? Ich mein, das gibt's doch nicht, dass man in .NET keine separaten Speicherbereiche haben kann, in die man Assemblies reinlädt.
    Unter Win32 gibt's das ja praktisch ewig 😕

    Schade, hab auch grad gelesen das es ein vereinfachtes Beispiel war.
    Komm dann machs wie du es am anfang ueberlegt hattest. Fackel das einfach in der Library.dll ab.



  • Jo, wird mir wohl nicht viel anderes übrig bleiben 😕 Das Interface bleibt erst mal gleich und intern stelle ich die Library.dll so um, dass man zukünftig flexibler ist. Mann, da macht man es sich ein einziges mal einfach und schon fliegt man auf die Fresse 😃
    Danke für eure Antworten 🙂 Wenn noch einer was wertvolles zum Thema AppDomain zu sagen hat, immer her damit!


Anmelden zum Antworten