Mein Problem ist wie folgt:
Ich habe eine Basisklasse, die abstrakt sein muss. Es hat mehrere abgeleitete Klassen mit jeweils eigenen Eigenschaften, die im Element Properties enthalten sind.
Ich muss in der Lage sein, eine neue Instanz einer dieser abgeleiteten Klassen zu erstellen, so dass alle Elemente äquivalent sind, aber das Ändern der neuen Instanz ändert das Original nicht.
Schließlich möchte ich es tun, ohne in jedem abgeleiteten Typ der Basisklasse fest codieren zu müssen. (Das wäre zwar die einfachste Lösung, aber das ist nicht der Punkt)
Alle abgeleiteten Klassen erfüllen eine "ist-a" -Beziehung zur Basisklasse.
Hier ist der Code:
%Vor%Das Problem mit diesem Code ist die BaseClass newKeyFrame = new BaseClass (); Linie. Da die Klasse abstrakt ist, können Sie keine Instanz davon erstellen.
Das Problem ist, dass ich in der Lage sein muss, den Konstruktor eines beliebigen Typs der abgeleiteten Klasse aufzurufen, da sie alle einen unterschiedlichen Code in ihren Konstruktoren haben, die nicht geteilt werden können.
Ich habe gehört, dass die Verwendung von Reflection eine brauchbare Lösung sein kann, ich habe jedoch keine Ahnung, wie.
Wie kann ich das lösen, ohne für jeden abgeleiteten Typ einen Casecode erstellen zu müssen?
Sie könnten createNewInstanceStep1
generic machen. Ich habe auch die Step2
geändert, um void
zu sein (ich erwarte, dass es die aktuelle Instanz ändert, also wäre die Rückgabe immer return this;
sowieso), weil es sonst nicht wirklich Sinn macht Ich würde es gerne hier benutzen. Wenn es nicht sinnvoll ist, es so zu ändern, dann wird mein gesamter Ansatz, diese Methode nur generisch zu machen, nicht funktionieren.
Und createNewInstance
verwendet jetzt die Reflektion, um das Äquivalent von return createNewInstanceStep1<this.GetType()>();
aufzurufen.
Wenn dies nicht funktioniert, ist ein anderer Ansatz selbstreferenzieller generischer Typ . Es ist jedoch gut, dies zu vermeiden, weil es verwirrend ist und insgesamt kein gutes Design.
%Vor%Sie können createNewInstanceStep1 eine geschützte void init-Methode erstellen, die dieses Objekt initiiert, und es im Konstruktor jeder Unterklasse aufrufen.
Wie werden Sie wissen, welche Art von Instanz erstellt werden soll? Wenn Sie eine vorhandene Instanz der abgeleiteten Klasse haben und eine andere Instanz erstellen möchten, die im Grunde mit ihr identisch ist, sollten Sie Ihren Basistyp eine geschützte virtuelle CloneBase
-Methode implementieren lassen, die MemberwiseClone
aufruft und die Kopie vollständig ausführt Basistyp weiß davon und eine öffentliche Methode Clone
, die nach CloneBase
kettet und auf den Basistyp umsetzt. Alle abgeleiteten Typen sollten CloneBase
auf Kette auf base.CloneBase
überschreiben und alle erforderlichen zusätzlichen Tiefenkopien hinzufügen (dieser Schritt kann weggelassen werden, wenn keine zusätzliche Deep-Copy-Logik erforderlich ist) und die public Clone
-Methode mit einem Schatten überschatten chains to CloneBase
und wandelt das Ergebnis in seinen Typ um [mit einem separaten CloneBase
wird es möglich, sowohl eine neue Clone
-Methode mit einer anderen Signatur zu deklarieren als auch die Grundklassenmethode zu überschreiben und zu verketten].
Wenn Sie eine vorhandene Instanz der neuen Klasse haben, deren Eigenschaften jedoch von einer anderen -Instanz kopiert werden sollen, könnte eine abstrakte ConstructInstanceLike(x)
-Methode verwendet werden, für die jeder abgeleitete Typ implementiert würde Rufen Sie einen seiner Konstruktoren auf oder klonen Sie sich selbst und ändern Sie den Klon so, dass er dem übergebenen Objekt entspricht. Keine der beiden Methoden ist fürchterlich elegant, aber beides kann funktionieren.
Wenn Sie keine vorhandene Instanz der neuen Klasse haben, benötigen Sie andere Mittel, um etwas vom passenden Typ zu erhalten. Der netteste Ansatz besteht wahrscheinlich darin, eine Sammlung von Func<TParams, TResult>
-Delegaten zu speichern, eine für jeden abgeleiteten Typ von Interesse, und dann eine dieser Funktionen aufzurufen, um ein Objekt eines assoziierten abgeleiteten Typs zu erzeugen. Es wäre auch möglich, eine Schnittstelle zu definieren
In vielen Fällen ist es jedoch einfacher, mit einem Delegierten zu arbeiten.
Tags und Links c# inheritance constructor abstract-class