Announcement

Collapse
No announcement yet.

Verändern einer Assembly zur Laufzeit

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Verändern einer Assembly zur Laufzeit

    Hallo,

    ich möchte meine Assemblies gerne zur Laufzeit ändern. Die Assembly sollte dabei bevor sie geladen wird, auf eine XML-Datei zugreifen, die im gleichen Verzeichnis liegt. Anhand der Informationen innerhalb der XML-Datei sollte sich die Assembly in die darin befindlichen Klassen mit den EIngeschaften automatisch anpassen.

    Konkret bedeutet dies: Ich habe aktuelle ein DICOM-Dictionary, wo ich auf die Eigenschaften nur durch Zahlen oder Zeichenketten zugreifen kann dieser Zugriff immer ein object als Resultat hat. Da es aber zum einen ungefähr 2000 Einträge gibt, die sich keiner merken kann und sich zum anderen der Datentyp automatisch aus dem Zugriff ergibt, möchte ich mir dynamisch mein Dictionary aufbauen, welches die Eigenschaften als Properties mit einem konkreten Datentyp angibt.

    Dies würde dann zur Laufzeit und zur Designzeit funktionieren (Natürlich nur solange wie keiner die XML-Datei verändert, davon kann ich aber ausgehen).

    Hat dies bisher schon jemand versucht? Meine Versuche schlugen insofern fehl als dass es keine DllMain Methode mit einem Einsprungspunkt gibt. static Methoden helfen mir dabei nicht weiter, da hier die Assembly ja bereits geladen wurde.

    Vielen Dank
    Martin

  • #2
    Originally posted by Martin Sedlmair View Post
    Die Assembly sollte dabei bevor sie geladen wird, auf eine XML-Datei zugreifen, die im gleichen Verzeichnis liegt.
    Martin,

    wie soll eine Assembly auf eine XML-Datei zugreifen, bevor sie geladen ist?

    Ich verstehe zwar nicht so ganz, was Du erreichen willst, aber schau Dir mal CodeDom an. Damit kannst Du Assemblies zur Laufzeit Deines Programms erzeugen und diese dann ausführen.

    Gruß
    Peter

    Comment


    • #3
      Vielleicht hab ich's jetz auch total falsch verstanden, aber wieso muss die komplette Assembly sich danach richten, was in der XML steht. Würde es nicht auch einfach eine Klasse tun, der man im Konstruktor mitteilt wie sie sich zu verhalten hat (z.B. indem man ihr den Datentyp mitteilt)? Wäre halt ein völlig anderer Denkansatz, aber vielleicht auch ein einfacherer

      Comment


      • #4
        Hallo,

        natürlich hast Du recht Peter, dass die Assembly erst etwas tun kann, wenn sie geladen wurde.

        Aktuell kann ich auf die Parameter, die in einer DICOM Struktur geladen wurden, nur mit Strings oder einer Zahl ansprechen (hier im Beispiel untenstehend über this[...]).

        Code:
        class DICOM
        {
           DataElement this[string Name]
          {
             get {...}
          }
        
           DataElement this[uint Tag]
          {
             get {...}
          }
        }
        Dies ist aber für den der die Library benutzen möchte nicht tragbar, da er die Tags bzw. Namen kennen muss. Die Namen/Tags ergeben sich aber erst, wenn eine DICOM-Datei geladen wurde. Somit ist aber auch erst dann der Datentyp verfügbar. Was ich haben möchte ist, dass ich durch die beschriebene XML-Datei der DICOM-Klasse eine Struktur vorgebe, etwa so:

        Code:
        class DICOM
        {
          string PatientName
          {
            get {...}
          }
        
          DateTime PatientBirthdate
          {
            get {...}
          }
        }
        Da ich das Ganze als Library verwenden möchte, will ich auch, dass die Struktur zur Entwicklunsgzeit sichtbar und vorhanden ist. Dazu muss quasi beim Laden der Assembly ein Aufruf innerhalb der Assembly erfolgen, der die XML-Struktur liest und die Assembly und deren Inhalt entsprechend umbaut. In einer DLL gabs es hierzu in der DllMain einen Aufruf zur Initialisierung in Assemblies habe ich dies bisher nicht gefunden. Nur für COM gab es entsprechende Attribute, zum Registriereren und Deregistrieren.

        Ist es jetzt ein wenig einsichtiger was ich tun will?

        Viele Grüße
        Martin

        Comment


        • #5
          So wie ich den DICOM Standard beim überfliegen verstehe ist der vollständig beschrieben enthält also eine Beschreibung aller möglichen Attribute. Wenn du das ganze als XML hast solltest es doch dazu auch eine XSD Schema mit der Beschreibung geben? Aus der XSD kannst du dir dann ganz einfach eine Klassenstruktur erzeugen lassen (XSD.exe aus dem Framework) die dann eine vollständige Obermenge der XML darstellt und alle Attribute als Properties enthält. Attribute die in deinem XML dann nicht enthalten sind sind dann halt null.

          Wenn du keine XSD hast, dein jetziges XML aber schon weitestgehend alle Attribute enthält die du brauchst kannst du dir daraus auch eine XSD erzeugen lassen. Ebenfalls wieder über die XSD.exe.

          Comment


          • #6
            Hallo Ralf,

            prinzipiell hast Du schon recht, das Problem dabei wäre nur, dass DICOM ca. 3000 verschiedene Attribute beinhalten kann, wobei dann viele auf null und nur. ca. 20% wären. Das dies natürlich auch bei einer reduizierten Form mit nur 20% möglich ist, ist schon klar, aber es wären halt nicht die 3000 Einträge.

            Die 3000 Einträge sind zudem für verschiedene Bildgebungsmodalitäten, sodass sich für jede einzelne Modalität nur ein Subset der verfügbaren Einträge ergibt.

            Ich könnte dies natürlich auf offline lösen und mir aus den XML/XSD auch den Code für die Assemblies vorher schon generieren. Diesen Schritt habe ich schon hinter mir, dabei auf festgestellt, dass es gute Lösung nur auf dem Weg praktiabel ist, so wie ich es mir mit dem Laden und Verändern der Assembly zur Laufzeit vorgestellt habe.

            Viele Grüße
            Martin

            Comment


            • #7
              Wenn du dir nur regelmäßig eine Untermengen der Klassenstruktur anhand einer typischen XSD (oder XML) machen möchtest so könntest du das was die xsd.exe macht in ein Custom Tool auslagern (in der XSD.exe steckt keine Magie alles was die benutzt befindet sich eigentlich recht gut gekapselt schon im Framework und ist so benutzbar).

              Heißt du würdest einfach die XSD (oder XML) in ein VisualStudio Projekt aufnehmen. Im Property Editor unter Custom Tool dein Custom Tool eintragen und sobald sich diese XSD ändert würde Visual Studio automatisch den Generierungsprozeß anstossen.

              So macht es Visual Studio übrigens bereits zum Beispiel bei Resourcen(resx) mit dem ResXFileCodeGenerator Custom Tool.

              Comment


              • #8
                Hallo Ralf,

                auch das Custom Tool habe ich schon hinter mir, ich habe mir sogar ein eigenes geschrieben, da die aktuellen Custom Tools nur eine Datei erstellen können. Wie gesagt, hier bei uns es es so, dass die DICOM dictionaries oft angepasst werden mussen und die meisten nur die Bibliothek verwenden ohne dabei Zugriff auf den Code zu haben.

                Siehst Du überhaupt eine Chance, dass das von mir vorgeschlagene Verfahren in .NET/C# möglich ist.

                Danke
                Martin

                Comment


                • #9
                  Ein Custom Tool scheint für mich eigentlich das Richtige zu sein.
                  Was hattest du den für Probleme dabei.

                  Es wird aus 1'er XSD(XML) 1'ne c# Datei erzeugt das sollte doch ok sein?

                  Comment


                  • #10
                    Vielleicht sollte ich noch etwas spezifischer werden. Zum einen ist es so, dass es für jede Modalität ein spezifiziertes DICOM Dictionary gibt, das bedeutet also, dass ich aus einer XSD ein oder mehrere Klassen bauen müsste, das wäre auch OK.

                    Das Problem hierbei ist aber, dass ich jedes Mal, wenn ich an der XML-Datei etwas verändere meine Klassen neu bauen müsste und genau das möchte ich vermeiden. Zudem muss ich die Custom Tools, wenn ich den mir ein eigenes baue um aus einer XML mehrere Klassen zu erzeugen, registrieren und allein das ist für mich schon ein Problem.

                    Warum das bei VS2008 so ist dass ich Custom Tools registrieren muss ist mir immer noch ein Rätsel, da ja alles auf der .NET Welt aufsetzt und ich entweder .NET Plugins gestellten könnte, die mein Custom Tool darstellen oder wenigstens eine DLL in C++ die eben Funktionen für das Custom Tool beinhaltet. So ist das Custom Tool aktuell noch eine alte COM-Klasse. Auch das möchte ich vermeiden.

                    Wir arbeiten aktuell für die DICOM Leseoutinen mit MATLAB. Das das zwar mir MATLAB eine leicht andere Sache ist mir klar, aber genau hier geht es eben eine DICOM-Datei zu laden, die sich anhand einer XML-Datei die Attribute aufbaut. Mit Matlab ist die Sache natürlich einfach, weil es interpretierter Code ist. Nachdem .NET aber mittlerweile in dieser Hinsicht genauso gut ist, Routinen zur Laufzeit zu verändern, scheint mir das der naheligendste Ansatz zu sein. Zudem möchte ich natürlich voll die Eigenschaften der Code Inspection und Code Completion mitnehmen.

                    Die Sache wäre dabei wesentlich einfacher, wenn ich einen Entry Point in einer Class Library habe. Nach mehrfachem Nachlesen habe ich jedoch herausgefunden, dass man für eine Class Library kein Startup Object definieren kann. Zudem kann man natürlich keine Methoden mehr exportieren. Die Attribute [ComRegister] [ComUnregister] um wenigstens COM-Klassen registrieren zu können bringen offensichtlich einen Funktionalität mit Methoden so zu exportieren, dass wenigstens RegSvr32 damit zurechtkommt.

                    Nun meine Frage: Gibt es wenigstens eine Möglichkeit eine Methode so zu markieren, dass ich beim Assembly.Load() innerhalb der zu ladenden Assembly irgendwie informiert werde?

                    Danke
                    Martin

                    Comment


                    • #11
                      Nun meine Frage: Gibt es wenigstens eine Möglichkeit eine Methode so zu markieren, dass ich beim Assembly.Load() innerhalb der zu ladenden Assembly irgendwie informiert werde?
                      Soweit ich weiß gibts da keinen Weg. Du müßtest schon deine eigene Assembly Lade Methode schreiben und verwenden so das diese explizit Code in deiner zu ladenden Assembly aufruft.

                      Warum das bei VS2008 so ist dass ich Custom Tools registrieren muss ist mir immer noch ein Rätsel
                      Die IDE von VS ist eine weitestgehen unmanaged auf COM aufbauende Applikation. Kein Wunder das das Plugin System dann auch auf COM aufbaut.
                      Aber was ist das Problem mit dem registrieren des Custom Tools in COM?
                      Wenn es Rechte Problem sind hättest du die sowieso auch ohne COM da die Custom Tools ja auch in der Registry im LocalMachine Hive eingetragen werden müssen damit VS den Namen der in VS als Custom Tool benutzt wird auf ein konkretes Executable zurückführen kann um dieses auszuführen.

                      Comment


                      • #12
                        Originally posted by Martin Sedlmair View Post
                        Nachdem .NET aber mittlerweile in dieser Hinsicht genauso gut ist, Routinen zur Laufzeit zu verändern, scheint mir das der naheligendste Ansatz zu sein.
                        Das wäre mir neu, dass man bereits geladenen .net-Code verändern kann.

                        Originally posted by Martin Sedlmair View Post
                        Nun meine Frage: Gibt es wenigstens eine Möglichkeit eine Methode so zu markieren, dass ich beim Assembly.Load() innerhalb der zu ladenden Assembly irgendwie informiert werde?
                        Ist mir nicht bekannt, aber Du könntest Deinen Klassen einen statischen Constructor verpassen. Dieser wird immer vor dem ersten Zugriff auf Klassenmethoden aufgerufen. Aber ich wüsste nicht in wie weit Dir das bei Deinem Problem hilft.

                        Originally posted by Martin Sedlmair View Post
                        Das Problem hierbei ist aber, dass ich jedes Mal, wenn ich an der XML-Datei etwas verändere meine Klassen neu bauen müsste und genau das möchte ich vermeiden.
                        Wo ist dabei ein Problem? Nach dem Speichern der Xml-Datei, drückst Du noch ein Knöpfchen, und startest ein Programm, das die Klassen neu generiert. Diese landen dann am Besten in einer Versionsverwaltung und verteilen sich darüber automatisch an alle Entwickler, welche dann natürlich noch ihren Programmcode anpassen müssen, weil sich ja die Klassen verändert haben. Das Problem hättest Du aber auch, wenn Du sich selbst verändernde Assemblies bauen würdest.

                        Also ich plädiere auch für ein "CustomTool". :-)

                        Just my 2 cents
                        Peter

                        Comment

                        Working...
                        X