Fügen Sie zur Laufzeit der Klasse POCO eine Eigenschaft hinzu

8

Ich habe ServiceStack OrmLite für mein Projekt ausgewählt, das eine reine datenorientierte Anwendung ist. Ich bin bereit, dem Endbenutzer zu erlauben, seine eigenen Objekttypen zu erstellen, die in einem XML-Format definiert sind, das verwendet wird, um Klassen zur Laufzeit zu generieren, indem CodeDOM .

Ich werde auch einige "System" -Objekte definieren, die von der Anwendung benötigt werden (zB User ), aber ich kann nicht alle Eigenschaften des Endbenutzers vorhersehen und deshalb suche ich nach einer Möglichkeit, die Klassen, die ich erstelle, zu erweitern in der Entwurfszeit. Beispiel unten

%Vor%

Der Endbenutzer möchte ein Email und ein Address haben. Er sollte in der Lage sein, die 2 Eigenschaften der Oberklasse hinzuzufügen und die ganze Klasse wird (was immer noch von OrmLite verwendet werden kann, da es das Überschreiben erlaubt:

%Vor%

Ich weiß, dass dies das Risiko birgt, das System zum Absturz zu bringen (wenn die Klasse bereits instanziiert ist), also suche ich nach dem besten Weg, dieses Problem zu vermeiden und die Notwendigkeit nachzuahmen, die ich habe.

    
Moslem Ben Dhaou 20.01.2013, 00:23
quelle

4 Antworten

4

Es scheint, dass es zwei Teile zu dem gibt, was Sie hier tun. Sie müssen Typen dynamisch erstellen, um die zusätzlichen Eigenschaften zu unterstützen. Sie müssen außerdem sicherstellen, dass Sie niemals doppelte Typen in Ihrer AppDomain haben, d. H. Zwei verschiedene Definitionen von User .

Generierung des Laufzeittyps

Die verschiedenen bereits angegebenen Vorschläge behandeln, wie die Typen erstellt werden. In einem Projekt hatten wir etwas Ähnliches. Wir haben eine Basisklasse mit den Kerneigenschaften und ein Wörterbuch zum Speichern der Eigenschaften der Erweiterung erstellt. Dann haben wir Reflection.Emit verwendet, um einen abgeleiteten Typ mit den gewünschten Eigenschaften zu erstellen. Jede Eigenschaftendefinition liest oder schreibt einfach in das Wörterbuch der Basisklasse. Da Reflection.Emit das Schreiben von Low-Level-IL-Code mit sich bringt, erscheint es zunächst kompliziert. Wir haben einige Beispiel-abgeleitete Klassen in einer anderen Klassenbibliothek geschrieben und kompiliert. Dies waren Beispiele für das, was wir zur Laufzeit tatsächlich erreichen müssten. Dann haben wir ildasm.exe verwendet, um zu sehen, welchen Code der Compiler erstellt hat. Dies machte es sehr einfach herauszufinden, wie wir zur Laufzeit den gleichen Code generieren konnten.

Vermeidung von Namespace-Kollisionen

Ihre zweite Herausforderung besteht darin, doppelte Typnamen zu vermeiden. Wir haben eine Guid (mit ungültigen Zeichen entfernt) an den Namen jedes generierten Typs angefügt, um sicherzustellen, dass dies nie passiert ist. Einfache Lösung, obwohl ich nicht weiß, ob Sie damit mit Ihrem ORM durchkommen könnten.

Wenn dies Servercode ist, müssen Sie auch die Tatsache berücksichtigen, dass Assemblys nie in .NET entladen werden. Wenn Sie also zur Laufzeit wiederholt neue Typen generieren, wird Ihr Prozess weiter wachsen. Das gleiche passiert im Client-Code, aber dies kann weniger ein Problem sein, wenn Sie nicht erwarten, dass der Prozess für einen längeren Zeitraum ausgeführt wird.

Ich sagte, dass Baugruppen nicht entladen werden; Sie können jedoch eine ganze AppDomain entladen. Wenn das also Servercode ist, könnte der gesamte Vorgang in einer eigenen Anwendungsdomäne ausgeführt werden, und anschließend abreißen, um sicherzustellen, dass die dynamisch erstellten Typen entladen werden.

    
Olly 28.01.2013, 17:04
quelle
0

Warum nicht ein Schlüsselwertpaar für alle seine Eigenschaften oder zumindest die dynamischen verwenden?

Ссылка

Sie können es so machen, wie Sie es mit Reflection beschreiben, aber es wird einen Leistungseinbruch erfordern, auf diese Weise können auch Eigenschaften entfernt werden.

    
Zach Leighton 20.01.2013 00:28
quelle
0

Das Projekt, an dem ich gerade arbeite, hat eine ähnliche Anforderung. Wir haben ein System bereits in Produktion und hatte eine Client-Anfrage Zusatzfelder.

Wir haben das gelöst, indem wir unserem Modell einfach eine CustomFields-Eigenschaft hinzugefügt haben.

%Vor%

Wir verwenden das seit ein paar Wochen ohne Probleme.

Ein weiterer Vorteil, den wir daraus ziehen konnten, war, dass jede Zeile ihre eigenen benutzerdefinierten Felder haben konnte, so dass wir sie pro Datensatz behandeln konnten, anstatt sie für jeden Datensatz zu benötigen.

    
Chris Forsyth 23.01.2013 18:06
quelle
0

Sehen Sie sich ExpandoObject an, das dynamische Sprachunterstützung bietet, um so etwas zu tun. Sie können damit Ihren POCO zur Laufzeit zusätzliche Eigenschaften hinzufügen. Hier ist ein Link zur Verwendung der DLR-Funktionen von .NET: Ссылка

    
ajawad987 27.01.2013 00:08
quelle