Benutzer mit den meisten Antworten
Ein Object kopieren - Meine Art scheint nicht zu gehen - Alternativen oder Lösungen

Frage
-
Hallo liebe Programmier-Kollegen da draußen.
Ich habe ein kleines Problem was mich schon länger stört. Wenn ich ein Object als eine Kopie benötige, bevor ich es endgültig übernehme, kenne ich nur die Möglichkeit der normalen Zuweisung:
MyClass copy = original;
Doch ist copy ja dann exakt das selbe Object und wenn ich dort Änderungen vornehme, dann werden die in original auch übernommen.
Dann gibt es ja noch die Möglichkeit, einfach alle Werte zu übernehmen:
MyClass copy = new MyClass() { wert1 = original.wert1, wert2 = original.wert2 //... };
Doch fand ich das zu kompliziert auf dauer. Vor allem weil man jeden neuen Wert überall ergänzen müsste.
__
Ich dachte mir also eine Methode zu schreiben. Diese arbeitet zwar mit Reflection, sollte aber für meine Anwendungen kein Nachteil sein.
public static T CopyObject<T> ( T original ) where T : new () { T toReturn = new T (); foreach ( PropertyInfo info info original.GetType().GetProperties () ) { toReturn.GetType ().GetProperty ( info.Name ).SetValue ( info.GetValue ( original ), toReturn ); } return toReturn; }
So sieht das ganze aus. Doch kommt nun ein Fehler im foreach-Block:
Ein Ausnahmefehler des Typs "System.Reflection.TargetException" ist in mscorlib.dll aufgetreten. Zusätzliche Informationen: Das Objekt stimmt mit dem Zieltyp nicht überein.
Es ist bestimmt ein simpler kleiner Fehler, doch finde ich ihn nach langem suchen nicht.
Es wäre toll wenn einer von euch mir die Lösung für dieses Problem liefern könnte, oder mir eine Alternative bieten kann.
Dank euch jetzt schon mal.
lg
- Bearbeitet Dr. Prof. Evil Samstag, 24. Oktober 2015 17:55
Antworten
-
Hallo,
man muss die Parameter von SetValue schon in der richtigen Reihenfolge übergeben:
toReturn.GetType ().GetProperty ( info.Name ).SetValue (toReturn, info.GetValue ( original ));
Tom Lambert - .NET (C#) MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Donnerstag, 29. Oktober 2015 09:14
- Als Antwort markiert Aleksander Chalabashiev Donnerstag, 5. November 2015 10:15
Alle Antworten
-
Hallo,
man muss die Parameter von SetValue schon in der richtigen Reihenfolge übergeben:
toReturn.GetType ().GetProperty ( info.Name ).SetValue (toReturn, info.GetValue ( original ));
Tom Lambert - .NET (C#) MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Donnerstag, 29. Oktober 2015 09:14
- Als Antwort markiert Aleksander Chalabashiev Donnerstag, 5. November 2015 10:15
-
Hi,
abgesehen davon, dass dein Code in komplexeren Klassen mit untergeordneten Objekten so nicht funktioniert (da dann für Eigenschaften, die selbst Objekte beinhalten, trotzdem nur ein Verweis erstellt wird) würde ich es mal mit binärer Serialisierung/Deserialisierung probieren. Das sollte besser klappen und auch die gesamte Hierarchie berücksichtigen.
Geht natürlich nur, wenn alle Klassen, die in der Struktur vorhanden sind, auch serialisierbar sind, in der Regel klappt das aber ganz gut.
Public Shared Function SerializeObjectBinary( ByVal DataObject As Object ) As Byte() Dim Result As Byte() Dim Serializer As New BinaryFormatter() Dim MemoryStream As New MemoryStream() Serializer.Serialize( MemoryStream, DataObject ) Result = MemoryStream.GetBuffer() MemoryStream.Close() MemoryStream.Dispose() Return Result End Function Public Shared Function DeserializeObjectBinary( Of T )( ByVal Content As Byte() ) As T Dim Result As T Dim Serializer As New BinaryFormatter() Dim MemoryStream As New MemoryStream( Content.Length ) Result = DirectCast( Serializer.Deserialize( MemoryStream ), T ) MemoryStream.Close() MemoryStream.Dispose() Return Result End Function
Der Code ist zwar jetzt in VB.NET, das sollte aber problemlos für dich umstellbar sein. Falls nicht, meld dich nochmal dazu.
Performancetechnisch ist das für einzelne Verwendung problemlos. Bei massenhafter Verarbeitung wäre eine Alternative ggfs. sinnvoller (aber auch komplizierter).
http://www.codeproject.com/Articles/151946/A-High-Performance-Binary-Serializer-using-Microso
Alternativ kannst Du natürlich auch eine Rekursion in deinen Code einbauen, der dann auch die Hierarchie berücksichtigt.
Zum Fehler selbst. Steht da wirklich
foreach ( PropertyInfo info info original.GetType().GetProperties () )
in deinem Code? Falls ja, sollte der eigentlich gar nicht laufen, da das zweite "info" wohl eher ein "in" sein sollte, oder?
Die zweite Zeile:
toReturn.GetType ().GetProperty ( info.Name ).SetValue ( info.GetValue ( original ), toReturn );
ist dann auch falsch, probier mal:
toReturn.GetType().GetProperty( info.Name ).SetValue( toReturn, info.GetValue( original ), null );
Unter Umständen wäre es auch sinnvoll, solche Zeilen in mehrere zu splitten, das erhöht die Übersichtlichkeit evtl. ein wenig.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community -
Hallo,
man muss die Parameter von SetValue schon in der richtigen Reihenfolge übergeben:
toReturn.GetType ().GetProperty ( info.Name ).SetValue (toReturn, info.GetValue ( original ));
Tom Lambert - .NET (C#) MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | SnippetsEhm ja. Ich danke dir. Wie ich das übersehen konnte ist mir ein Rätsel. :P
lg