Angenommen, ich habe eine Klasse namens Foo
.
Ich kann die Klasse Foo
nicht ändern, aber ich möchte sie um eine Eigenschaft mit dem Namen Bar
vom Typ string
erweitern.
Außerdem habe ich noch viel mehr Klassen wie Foo
, also bin ich an einer 'generischen' Lösung interessiert.
Ich suche nach ExpandoObject
, dynamic
und es gibt mir das Ergebnis, nach dem ich frage, aber ich habe mich gefragt, ob es möglich wäre, ohne dynamic
...
Ihr Problem kann relativ einfach gelöst werden, indem Sie Reflection.Emit und Laufzeitcode-Generierung verwenden.
Angenommen, Sie haben jetzt die folgende Klasse, die Sie erweitern möchten.
%Vor%Diese Klasse repräsentiert eine Person und enthält eine Eigenschaft namens Alter , die das Alter der Person darstellt.
In Ihrem Fall möchten Sie auch die Eigenschaft Name des Typs string hinzufügen, um den Namen der Person darzustellen.
Die einfachste und am besten optimierte Lösung wäre dann, die folgende Schnittstelle zu definieren.
%Vor%Diese Schnittstelle, die zur Erweiterung Ihrer Klasse verwendet wird, sollte alle alten Eigenschaften enthalten, die Ihre aktuelle Klasse enthält, und die neuen, die Sie hinzufügen möchten. Der Grund dafür wird in einem Moment klar werden.
Sie können jetzt die folgende Klassendefinition verwenden, um Ihre Klasse tatsächlich zu erweitern, indem Sie zur Laufzeit einen neuen Typ erstellen, der sie auch von der oben erwähnten Schnittstelle ableiten wird.
%Vor%Um diese Klasse tatsächlich zu verwenden, führen Sie einfach die folgenden Codezeilen aus.
%Vor%Sie können jetzt sehen, dass der Grund dafür, dass wir eine Schnittstelle verwendet haben, um unsere neu erstellte Klasse zu erweitern, so ist, dass wir eine typsichere Möglichkeit haben, auf ihre Eigenschaften zuzugreifen. Wenn wir einfach einen Objekttyp zurückgeben würden, wären wir gezwungen, auf seine Eigenschaften durch Reflexion zuzugreifen.
BEARBEITEN
Die folgende modifizierte Version kann jetzt komplexe Typen innerhalb der Schnittstelle instanziieren und die anderen einfachen implementieren.
Die Definition der Person-Klasse bleibt gleich, während die IPerson-Schnittstelle jetzt die folgende ist.
%Vor%Die DynamicExtension-Klassendefinition ändert sich nun wie folgt:
%Vor%Wir können jetzt einfach die folgenden Codezeilen ausführen, um alle geeigneten Werte zu erhalten.
%Vor%Als meine Kommentare sehr ausführlich wurden, dachte ich, ich würde eine neue Antwort hinzufügen. Diese Antwort ist vollständig Marios Arbeit und Denken, nur meine kleine Ergänzung, um zu veranschaulichen, was ich vermitteln möchte.
Es gibt ein paar kleinere Änderungen am Beispiel von mario, die diese Arbeit sehr gut machen, nämlich nur die Tatsache ändern, dass die vorhandenen Eigenschaften als Klassenobjekt hinzugefügt werden, anstatt die gesamte Klasse zu duplizieren. Wie auch immer, hier ist, wie es aussieht (nur geänderte Abschnitte hinzugefügt, alles andere bleibt nach der Antwort von Mario):
%Vor% Für die Schnittstelle IPerson
fügen wir die tatsächliche Klasse Person
hinzu, anstatt die Eigenschaften zu kopieren:
Dies führt zu einer aktualisierten Verwendung von:
%Vor% Hoffe, das hilft dem ursprünglichen OP, ich weiß, dass es mich dazu gebracht hat zu denken, dass die Jury noch nicht entschieden hat, ob die Person
-Klasse in der Methode auf die gleiche Ebene reduziert werden sollte wie die neuen Eigenschaften !! In der Tat sollte die Verwendung der Zeile new DynamicExtension<Person>().ExtendWith<IPerson>();
ein vollständig erweitertes neues Objekt zurückgeben - inklusive Intellistence. Tough Call - hmmm ...
Tags und Links c# reflection dynamic