[Reflection -> SetValue]
-
Hi,
ich hab ein kurzes Beispiel Programm geschrieben was mein Problem
simuliert.
Frage: Wie bekomme ich die zwei letzten SetValue()- Beispiele zum laufen ohne den Typ der Properties in der Klasse direkt ändern zu müssen, wie es im ersten Beispiel getan habe.Ich bekomme für Test2 und Test3 folgende Ausnahmen:
Das Objekt mit dem Typ "TestReflections.ITest[]" kann nicht in den Typ "TestReflections.TestClass2[]" konvertiert werden.
Ein Objekt muss IConvertible implementieren.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace TestReflections { public interface ITest { } public class TestClass1 : ITest { string mName = "TestClass1"; } public class TestClass2 : ITest { string mName = "TestClass2"; } public class TestClass3 { private ITest[] mTest1; private TestClass1[] mTest2; private TestClass2[] mTest3; public ITest[] Test1 { get { return mTest1; } set { mTest1 = value; } } public TestClass1[] Test2 { get {return mTest2; } set { mTest2 = value; } } public TestClass2[] Test3 { get { return mTest3; } set { mTest3 = value; } } } class Program { public static ITest[] GetSomeTest1() { ITest[] tTest = new ITest[3]; tTest[0] = new TestClass1(); tTest[1] = new TestClass1(); tTest[2] = new TestClass1(); return tTest; } public static ITest[] GetSomeTest2() { ITest[] tTest = new ITest[3]; tTest[0] = new TestClass2(); tTest[1] = new TestClass2(); tTest[2] = new TestClass2(); return tTest; } static void Main(string[] args) { TestClass3 tClass3 = new TestClass3(); Type tObjectType = tClass3.GetType(); PropertyInfo tPropInfo = tObjectType.GetProperty("Test1", BindingFlags.Public | BindingFlags.Instance); //geht Object tValues = (Object)GetSomeTest1(); tPropInfo.SetValue(tClass3, tValues, null); tPropInfo = tObjectType.GetProperty("Test2", BindingFlags.Public | BindingFlags.Instance); //geht nicht try { tValues = Convert.ChangeType(tValues, tPropInfo.PropertyType); tPropInfo.SetValue(tClass3, tValues, null); } catch(Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message.ToString()); } tPropInfo = tObjectType.GetProperty("Test3", BindingFlags.Public | BindingFlags.Instance); try { tValues = (Object)GetSomeTest2(); //tValues = Convert.ChangeType(tValues, tPropInfo.PropertyType); tPropInfo.SetValue(tClass3, tValues, null); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message.ToString()); } } } }
-
Ok,ich habe jetzt eine Lösung
gefunden, wenn jemand eine elegantere weiß immer her damittPropInfo = tObjectType.GetProperty("Test2", BindingFlags.Public | BindingFlags.Instance); //geht nicht try { Array tArray0 = GetSomeTest1(); Array tArray = Array.CreateInstance(tPropInfo.PropertyType.GetElementType(), tArray0.Length); tPropInfo.SetValue(tClass3, tArray, null); for (int tIdx = 0; tIdx < 3; tIdx++) tArray.SetValue(tArray0.GetValue(tIdx), tIdx); tPropInfo.SetValue(tClass3, tArray, null); } catch(Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message.ToString()); }
-
Hallo
Das was du vorhast, sollte auch nicht gehen, ohne ein SerValue, also mit direkter Zuweisung. Und Zwar liegt des an deinem Array-Typ, du definierst ein Array von der Basis-Klasse und willst es in ein Array einer abgeleiteten Klasse zuweisen.
Mal als Beispiel an Klassen:
class Base {} class Derivid : Base {} Base base = new Derivid(); Derivid baseDev = base; // das ist nicht direkt möglich nur explizit Base[] b = nee Base[3]; Derivid[] d = (Derivid[])b; // funktioniert ebenfalls nicht
Und das die Array Zuweisung nicht geht ist gut so, da du im Base Array auch Objekte von einer anderen Klasse (zB: Derivid die von Base abgeleitet ist) eintragen könntest und dies zu Fehlern führt.
Der wirklich richtige Weg ist hier, sich auf eine Basis Klasse/Interface zu einigen. Entweder stellst du bei den Eigenschaften alle aufs Interface oder du erzeugt bei der Rückgabe in den Funktionen ein Array der Klasse und nicht eins des Interface.
Des sollte funktionieren, aber wirklich gut find ich es nicht, besser wäre den Return-Wert auch mit anzupassen.
Public ITest[] GetTest2() { Base[] res = (Base[])new Derivid[3]; ... Return res; }
Mfg marco
-
Hallo Marco,
danke für deine Antwort. Mein letztes Beispiel funktioniert schon,
sonst hätte ich es ja nicht gepostet
Die SetValue - Funktion war auch enthalten,die hast du vielleicht nur übersehen.Deine Variante finde ich trotzdem besser,ich hab es auch schon getestet. Ich hatte mal wieder 1A nen Brett vor den Kopf, ich bin überhaupt nicht auf die Idee gekommen das Rückgabearray vom eigentlichen Typ anzulegen
Ich hab immer schön das ITest[] Array angelegt.
ok Vielen dank
-
Hallo deine Lösung hab ich schon gesehen
im Endefekkt ist sie nicht viel anders als meine mit der Anpassung des Array-Typs nur das du es danach machst.
Und meine Antwort war auf deine Frage nach einer eleganteren Lösung gemünzt :). Und einer kurzen Erklärung worin genau der Fehler bestand.
Mfg Marco