Gibt es eine Möglichkeit Field
(oder FieldInfo
, vielleicht ist das das Gleiche) zu einer Klasse zur Laufzeit hinzufügen?Wie kann ich dynamisch ein Feld zu einer Klasse hinzufügen in C#
Antwort
Sie können eine Klassendefinition zur Laufzeit nicht ändern. Sie können jedoch eine neue Klasse erstellen, die von der ursprünglichen Klasse erbt (wenn es nicht sealed
ist) und das Feld deklariert. Sie können dies tun, indem Sie den entsprechenden IL-Code mit System.Reflection.Emit
ausgeben.
Nein, C# erlaubt monkey-patching nicht.
Sie können neue Klassen mit CodeDOM oder Reflection.Emit generieren, aber Sie können vorhandene nicht ändern.
Es heißt Affen-Patching? Woher kam dieser Begriff? –
Keine Ahnung, wo es herkommt, aber ich habe einen Link zum Wikipedia-Eintrag hinzugefügt. –
Monkey Patching ist ein Begriff, der von Ruby kommt. Jeff Atwood hat vor einigen Jahren in einem Blogbeitrag darüber geschrieben. –
Nicht genau.
Sie können jedoch ICustomTypeDescriptor implementieren, um es anzunähern, und dann einfach eine Hashtabelle verwenden, um die Feldname/Wert-Paare zu speichern. Ein Großteil des Frameworks, das Reflektionen verwendet, fragt zuerst nach ICustomTypeDescriptor.
Danke, ich habe diesen Ansatz versucht, aber es funktioniert nicht für mich. Ich versuche, die IExpando-Schnittstelle zu aktivieren, um JavaScript-Code-Aufrufen in der C# -Klasse nicht angefragte Felder zuzulassen. Beispiel: var o = neues ActiveXObject ('mCom'); o.ArbitraryField = "Foo"; Bitte beachten Sie, dass ArbitraryField in meiner Klasse nicht existiert. –
Haben Sie gerade versucht, IReflect zu implementieren? Es ist die Möglichkeit, IDispatch/IExpando für Interop mit dynamischen Sprachen zu implementieren (zumindest vor C# 4.0). http://msdn.microsoft.com/en-us/library/system.reflection.ireflect.aspx Ich habe genau diese Sache mit einer Hashtable-Implementierung getan und es funktioniert gut – codekaizen
Nicht bis C# 4.0, das dynamische Nachschlagen hinzufügt und auf der CLR 4.0 basiert, die die DLR enthält, und dann wird es nicht zu einer Klasse hinzufügen, da Klassen nicht im Bild sein werden.
Ich würde nicht denken, dass dies möglich sein wird in C# 4.0. Ich denke, dass Sie bestehende Typen nicht ändern können. Ich kann mir jedoch vorstellen, dass Sie ein dynamisches Objekt (z. B. von Ruby) erstellen und dann ändern können. –
Das ist, was ich mit "nicht streng zu einer Klasse hinzufügen, da Klassen nicht auf dem Bild sein werden" gemeint. Vielmehr können einzelne Objekte, die von 'dynamisch' referenziert werden, die Zuweisung zu einer Eigenschaft akzeptieren, die vorher nicht existierte, und sich damit beschäftigen, indem sie dynamisch eine Eigenschaft hinzufügen. –
C# lässt dies nicht zu, da alle Klassen auf Metadaten basieren. Die CLR (nicht C#) verbietet das Hinzufügen von Feldern zu Metadaten zur Laufzeit (1). Nur so kann C# bei runitme ein Feld hinzufügen.
Dies ist anders als dynamische Sprachen wie IronPython, die im Wesentlichen keine konkreten Metadaten-Klassen haben. Sie haben dynamischere Strukturen, die zur Laufzeit geändert werden können. Ich glaube, dass IronPython seine Mitglieder (Felder und Methoden) einfach in einer Hashtabelle hält, die zur Laufzeit leicht geändert werden kann.
In C# 3.0 verwenden Sie Reflection.Emit am besten. Dies erzeugt jedoch eine völlig neue Klasse gegenüber der Änderung einer bestehenden Klasse.
(1) Es gibt bestimmte APIs wie die Profiling-APIs oder ENC, die dies erlauben, aber ich bin mir nicht sicher, ob ihre Möglichkeiten zum Hinzufügen von Feldern erweitert werden.
wie bereits erwähnt, ist dies nicht möglich. Was ist der Grund für deine Frage? Wenn Sie einige zusätzliche Daten in der Klasse dynamisch speichern müssen, dann könnte man wahrscheinlich nur Wörterbuch verwenden:
class My {
Dictionary<string, object> data;
public My() { data = new Dictionary<string, object>(); }
}
.. aber es hängt wirklich davon ab, was Sie eigentlich erreichen wollen?
Mein Ziel ist die Implementierung der IExpando-Schnittstelle. Mein oberstes Ziel ist es, JavaScript-Code zu erlauben, dynamisch und auf "Javascript-Weise" Felder zum ActiveX-Objekt hinzuzufügen. Beispiel: var myobj = neues ActiveXObject ('server.object'); myobj.ArbitraryField = "etwas"; Bitte beachten Sie, dass ArbirtaryField nicht existiert –
Siehe this question für eine einfache Möglichkeit, um es in C# 4.0 zu tun, indem eine ExpandoObject
als IDictionary
, die die Werte zum Wörterbuch Eigenschaften des Objekts hinzugefügt werden wirft. Ich zeige dies in another answer of mine und zeige, dass sie tatsächlich zu Eigenschaften werden.
Dies ist jedoch nur mit einer Instanz von ExpandoObject
oder durch Sub-Classing DynamicObject
möglich.
Es kann auch möglich sein, mit anderen Klassen zu verwenden, wenn sie IDynamicMetaObjectProvider
implementieren, aber ich denke, es gibt zu viel Arbeit beteiligt, damit es richtig funktioniert.
Vielleicht könnten Sie das Decorator-Muster verwenden.
In der objektorientierten Programmierung ist das Dekorationsmuster ein Entwurfsmuster, das das Hinzufügen von Verhalten zu einem einzelnen Objekt entweder statisch oder dynamisch ermöglicht, ohne das Verhalten anderer Objekte derselben Klasse zu beeinflussen.
möglich Duplikat [Wie kann ich dynamische Eigenschaften in C#?] (Http://stackoverflow.com/questions/947241/how-do-i-create-dynamic-properties-in-c) – nawfal