Autor |
Beitrag |
Palladin007
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Di 02.09.14 00:36
Moin,
ich habe eine Klasse, die von DynamicObject erbt.
Die Methode GetDynamicMemberNames, TryGetMember und TrySetMember habe ich implementiert und das dynamische Objekt lässt sich auch wunderbar benutzen.
Jetzt möchte ich das aber in das Interface casten, das die Properties des Typs vorgibt.
Alle Member des jeweiligen Interfaces werden bereits in dem dynamischen Typ implementiert, casten kann ich aber nicht.
Ich habe bisher nicht viel dazu gefunden, wie ich TryConvert richtig implementiert, außer das Stichwort TypeBuilder.
An den habe ich mich bisher noch nicht heran getraut, daher die Frage: Gibt es auch einen einfacheren Weg?
Gruß
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Di 02.09.14 15:44
Zeig mal was du tust dann versteh ich das vielleicht. Ich durchschaue nicht mal ob das Interface jetzt für den DynamicObject Abkömmling gemeint ist, für beliebige Properties, dynamische Properties oder ob sich das nur auf Typen die von den Properties verwendet werden gemeint ist.
|
|
Palladin007 
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Di 02.09.14 16:07
Ich bin gerade nicht Zuhause, daher kann nichts zeigen.
Aber ich kann versuchen, es besser zu beschreiben.
Ich möchte eine Klasse haben, die als Grundlage ein Interface bekommt und anschließend konkretere Informationen zu den Membern erhält.
Sie soll soll dann Objekte erzeugen können, die das Interface implementieren und diese konkreteren Angaben ebenfalls unterstützen.
Dabei ist es völlig egal, was das für ein Interface ist, die Implementierung läuft dynamisch ab.
Daher habe ich das DynamicObjekt gebaut, was das intern regelt. Das funktioniert soweit auch, allerdings möchte ich nicht, dass beim Aufruf dann dynamic zurück gegeben wird, sondern das Interface, welches das Objekt implementiert. Die Properties sind ja da.
Daher war die Frage, ob es eine Technik gibt, die ein Objekt in einen bestimmten Typen casten kann, wenn es alle Anforderungen, die das Interface vorgibt, erfüllt.
Oder muss ich dafür manuell zur Laufzeit einen Typ erzeugen und dann davon Objekte erstellen?
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Di 02.09.14 17:17
Zitat: | Daher war die Frage, ob es eine Technik gibt, die ein Objekt in einen bestimmten Typen casten kann, wenn es alle Anforderungen, die das Interface vorgibt, erfüllt.
Oder muss ich dafür manuell zur Laufzeit einen Typ erzeugen und dann davon Objekte erstellen? |
Es wäre jedenfalls kein casten im eigentlichen Sinn. Wo kommt jetzt bei deiner Überlegung dynamic ins Spiel beim ~Quell~ oder ~Ziel~ Typ?
Das einzige was so nach dieser Richtung aussähe (und ich kenne) wäre der DynamicProxy aus dem Castle Windsor Project. Ob man damit aber ein vorher nicht an der Klasse vorhandenes Interface in die erstellte Proxy Klasse rein lügen kann wäre mir gerade nicht bewußt aber denkbar.
Edit: Hattest du dir sowas gedacht?
|
|
Palladin007 
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Di 02.09.14 23:38
Stimmt, ein echtes Casten ist es nicht, sondern eher so gefaked. Aber genau das will ich ja erreichen, dass es nach außen echt aus sieht.
Die Überlegung dynamic kam ins Spiel, wegen DuckTyping. Dort ist es ja so, dass nicht der beim Deklarierten verwendete Typ der Typ des Objektes fest legt, sondern die Member Objektes.
Und diese Member kann man zur Laufzeit ändern, was bedeutet, dass man das Objekt erweitern und dann auch in einen entsprechend anderen Typ casten kann.
Laut Wiki unterstützt C# das.
Eine externe Library wollte ich eigentlich nicht verwenden, zum Einen aus Übung, dass ich das mal kenne und zum Anderen, weil ich das eventuell für mehrere Projekte nutzen will und da aktuell auch schon ein Auftrag dabei ist. Der Auftragist noch unbezahlt, der wird dann nur in die Ausbildung mit eingerechnet, aber es kann ja auch mal einen bezahlten Auftrag geben.
Wenn mein Gedanke gut funktioniert, dann möchte ich dabei keine exteren Abhängigkeiten haben.
Etwas Ähnliches wie den DictionaryAdapter gibt es in .NET schon, das ExpandoObject.
Das baut einen dynamischen Typ anhand eines Dictionaries zusammen. Das nutze ich, wenn ich mal unbedingt einen DataReader nutzen muss. Der DataRecord wird dann in ein dynamic Object umgebaut, enthält intern aber nur ein Dictionary.
PS: Oder ist adapter vom Typ IHelloWorld? Wenn ja, dann ist das ungefähr das, was ich will.
Was ich will, läuft ungefähr so ab:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| class IPerson { string Name { get; set; } DateTime Birthday { get; } }
var typeDefinition = new TypeDefinition<IPerson>();
tapeDefinition.RegisterProperty(p => p.Name, isRequired: true); tapeDefinition.RegisterProperty(p => p.Birthday, isRequired: true);
var birthday = DateTime.Now; var name = "Wrong Name";
IPerson person = typeDefinition.CreateObject(name, birthday);
person.Name = "Correct Name"; |
Und das theoretisch mit jedem Typ.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 03.09.14 00:13
Zitat: | PS: Oder ist adapter vom Typ IHelloWorld? |
Wenn du das Beispiel des DictionaryAdapter ansprichst dann ja. Du bekommst du eine echte Klasse die IHelloWorld implementiert keinen dynamischen Fake
Zitat: | Was ich will, läuft ungefähr so ab: |
Das sieht aus wie ein typisches Mocking Framework um zum testen einer Klasse alle Abhängigkeiten(die nur Interfaces sind) durch Mocks zu ersetzten. Die können dann auch Methoden u.s.w. nachstellen nicht nur reine ~Speicher~ Properties.
Du versuchst doch nicht auch noch ein Mocking Framework zu schreiben? Da gibt es mittlerweile genug von. Genauso wie von NUnit klonen
in z.b. Moq(das auch den angesprochenen DynamicProxy verwendet) sähe dein Beispiel so aus.
C#-Quelltext 1: 2: 3: 4: 5: 6:
| var personMock = new Mock<IPerson>(); personMock.SetupProperty(x => x.Name, "Wrong Name"); personMock.SetupProperty(x => x.Birthday, DateTime.Now);
IPerson person = personMock.Object; person.Name = "Correct Name"; |
Wenn du es gerne selbst machen willst die Frameworks sind Open Source. Inspirieren lassen tut nicht weh.
|
|
Palladin007 
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Mi 03.09.14 00:53
Joa, genau sowas will ich machen mit genau dem Hintergrund: Mocking
Ich hätte auch Methoden angeboten, Properties waren nur der Anfang, weil ich dafür direkt ein Projekt hätte, wo ich es in der Praxis testen kann.
Ursprügnlich wollte ich es schon selber machen, aber da es das anscheinend ja schon gibt und deinem Beispiel nach zu Urteilen ziemlich genau so, wie ich mir das vorgestellt habe.
Im Prinzip baue ich also nur etwas nach, das schon deutlich weiter ist und zahllos oft getestet wurde.
Ich schau mir mal die Frameworks an, vielleicht ist ja was dabei.
Um auf die Frage zurück zu kommen:
Ist TryConvert also garnicht für die Anwendung gedacht, die ich vorgesehen habe, also nur für wirkliches konvertieren zu irgendwelchen Typen?
Das würde erklären, warum ich nur Winz-String-Beispiele gefunden habe.
Und kann ich auch davon ausgehen, dass ich mein Vorhaben also garnicht mit DynamicObject lösen sollte, sondern mir direkt den Typ im Speicher bauen sollte?
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 03.09.14 09:46
Hab mich mit den Sachen noch nicht intensiv auseinandergesetzt um das wirklich abschließend beurteilen zu können. Aber die ganze DynamicObject und IDynamicMetaObjectProvider Geschichten sind für mich explizit für die dynamische Nutzung gedacht heißt deren Magie wirken eher beim Editieren und weniger zur Laufzeit, aka ein dynamischer erzeugter Typ ist nicht wirklich ein eigener Typ der beliebiges ein Interface geben könnte. Eigentlich willst du den Typ zur Laufzeit auch nicht wirklich dynamisch er soll ja nur das Interface erfüllen ohne das man dafür manuell eine Klasse schreiben muß. Dafür braucht man was aus der stark typisierten Welt in der auch Interface stattfinden. Also echte Klassen. Das macht der DynamicProxy und benutzt dazu intensiv das MSIL Generierungszeugs aus dem System.Reflection.Emit Namespace.
|
|
Palladin007 
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Mi 03.09.14 10:17
Vermutlich hast du Recht und ich muss mein ganzes bisheriges Vorgehen über den Haufen werfen.
Vielleicht kann ich die Klasse dann auch einmal erstellen und irgendwo ablegen. Das Erstellen der Objekte selber geht dann hoffentlich genauso schnell, wie bei jeder "richtigen" Klasse sonst auch.
Bis dahin danke für die Hilfe.
Ich werde vermutlich doch selber das umsetzen, gerade weil das so ein mächtiges Feld in .NET ist und es daher ganz praktisch sein könnte, zu wissen, wie man damit richtig und performant umgeht.
|
|
|