Ist es möglich, einer abgeleiteten Klassenreferenz ein Basisklassenobjekt mit einer expliziten Typumwandlung in C # zuzuweisen?
Ich habe es versucht und es entsteht ein Laufzeitfehler.
Ist es möglich, einer abgeleiteten Klassenreferenz ein Basisklassenobjekt mit einer expliziten Typumwandlung in C # zuzuweisen?
Ich habe es versucht und es entsteht ein Laufzeitfehler.
Antworten:
Nein. Ein Verweis auf eine abgeleitete Klasse muss sich tatsächlich auf eine Instanz der abgeleiteten Klasse (oder null) beziehen. Wie würden Sie sonst erwarten, dass es sich verhält?
Beispielsweise:
object o = new object();
string s = (string) o;
int i = s.Length; // What can this sensibly do?
Wenn Sie eine Instanz des Basistyps in den abgeleiteten Typ konvertieren möchten, empfehlen wir Ihnen, eine Methode zum Erstellen einer geeigneten Instanz des abgeleiteten Typs zu schreiben. Oder sehen Sie sich Ihren Vererbungsbaum noch einmal an und versuchen Sie, ihn neu zu gestalten, damit Sie dies nicht erst tun müssen.
Derived
, aber Sie können eine Derived
Referenz als Base
Referenz behandeln.
Base
und der andere erstellt eine Instanz von Derived
. Wenn Sie eine virtuelle Methode aufrufen, für b
die überschrieben wurde Derived
, wird das Derived
Verhalten angezeigt , wenn Sie eine Instanz von haben Derived
. Es ist jedoch nicht wirklich angebracht, in einem Stack Overflow-Kommentarthread auf die Details einzugehen - Sie sollten wirklich ein gutes C # -Buch oder Tutorial lesen, da dies ziemlich grundlegende Dinge sind.
Nein, das ist nicht möglich, da das Zuweisen zu einer abgeleiteten Klassenreferenz so aussehen würde, als würde man sagen "Basisklasse ist ein voll funktionsfähiger Ersatz für abgeleitete Klassen, sie kann alles, was die abgeleitete Klasse kann", was nicht zutrifft, da abgeleitete Klassen im Allgemeinen angeboten werden mehr Funktionalität als ihre Basisklasse (zumindest ist das die Idee hinter der Vererbung).
Sie können einen Konstruktor in die abgeleitete Klasse schreiben, indem Sie ein Basisklassenobjekt als Parameter verwenden und die Werte kopieren.
Etwas wie das:
public class Base {
public int Data;
public void DoStuff() {
// Do stuff with data
}
}
public class Derived : Base {
public int OtherData;
public Derived(Base b) {
this.Data = b.Data;
OtherData = 0; // default value
}
public void DoOtherStuff() {
// Do some other stuff
}
}
In diesem Fall würden Sie das Basisobjekt kopieren und ein voll funktionsfähiges abgeleitetes Klassenobjekt mit Standardwerten für abgeleitete Elemente erhalten. Auf diese Weise können Sie auch das von Jon Skeet aufgezeigte Problem vermeiden:
Base b = new Base();//base class
Derived d = new Derived();//derived class
b.DoStuff(); // OK
d.DoStuff(); // Also OK
b.DoOtherStuff(); // Won't work!
d.DoOtherStuff(); // OK
d = new Derived(b); // Copy construct a Derived with values of b
d.DoOtherStuff(); // Now works!
Ich hatte dieses Problem und löste es, indem ich eine Methode hinzufügte, die einen Typparameter verwendet und das aktuelle Objekt in diesen Typ konvertiert.
public TA As<TA>() where TA : Base
{
var type = typeof (TA);
var instance = Activator.CreateInstance(type);
PropertyInfo[] properties = type.GetProperties();
foreach (var property in properties)
{
property.SetValue(instance, property.GetValue(this, null), null);
}
return (TA)instance;
}
Das bedeutet, dass Sie es in Ihrem Code wie folgt verwenden können:
var base = new Base();
base.Data = 1;
var derived = base.As<Derived>();
Console.Write(derived.Data); // Would output 1
Wie viele andere geantwortet haben: Nein.
Ich verwende den folgenden Code in den unglücklichen Fällen, in denen ich einen Basistyp als abgeleiteten Typ verwenden muss. Ja, es ist ein Verstoß gegen das Liskov-Substitutionsprinzip (LSP), und ja, meistens bevorzugen wir die Komposition gegenüber der Vererbung. Requisiten an Markus Knappen Johansson, auf dessen ursprünglicher Antwort dies basiert.
Dieser Code in der Basisklasse:
public T As<T>()
{
var type = typeof(T);
var instance = Activator.CreateInstance(type);
if (type.BaseType != null)
{
var properties = type.BaseType.GetProperties();
foreach (var property in properties)
if (property.CanWrite)
property.SetValue(instance, property.GetValue(this, null), null);
}
return (T) instance;
}
Erlaubt:
derivedObject = baseObect.As<derivedType>()
Da es Reflexion verwendet, ist es "teuer". Verwenden Sie entsprechend.
user-defined conversions to or from a base class are not allowed
Ich sehe die Gründe dafür, bin aber enttäuscht. wie es so viel Spaß gemacht hätte, wenn es dies erlaubt hätte ..
if (type.BaseType != null)
Anweisung zu Markus Knappen Johanssons A hinzugefügt haben . Warum ist das so? Dies bedeutet, dass die Aufrufe eingegeben werden können, die nicht von MyBaseClass abgeleitet sind (oder was auch immer). Mir ist klar, dass es immer noch einen Compilerfehler verursacht, wenn es myDerivedObject zugewiesen wird. Wenn es jedoch nur als Ausdruck verwendet wird, wird es kompiliert und zur Laufzeit einfach ein myDerivedObject erstellt, ohne dass Daten von "myBaseObject" kopiert werden. Ich kann mir keinen Anwendungsfall dafür vorstellen.
Heute stand ich vor dem gleichen Problem und fand eine einfache und schnelle Lösung für das Problem mit JsonConvert
.
var base = new BaseClass();
var json = JsonConvert.SerializeObject(base);
DerivedClass derived = JsonConvert.DeserializeObject<DerivedClass>(json);
Wie alle hier sagten, ist das nicht direkt möglich.
Die Methode, die ich bevorzuge und die ziemlich sauber ist, ist die Verwendung eines Object Mapper wie AutoMapper .
Es übernimmt die Aufgabe, Eigenschaften automatisch von einer Instanz in eine andere (nicht unbedingt vom gleichen Typ) zu kopieren.
Erweitern der Antwort von @ ybo - dies ist nicht möglich, da die Instanz der Basisklasse keine Instanz der abgeleiteten Klasse ist. Es kennt nur die Mitglieder der Basisklasse und weiß nichts über die Mitglieder der abgeleiteten Klasse.
Der Grund, warum Sie eine Instanz der abgeleiteten Klasse in eine Instanz der Basisklasse umwandeln können, liegt darin, dass die abgeleitete Klasse tatsächlich bereits eine Instanz der Basisklasse ist, da diese Mitglieder bereits vorhanden sind. Das Gegenteil kann nicht gesagt werden.
Sie können eine Variable , die als Basisklasse eingegeben wird, in den Typ einer abgeleiteten Klasse umwandeln. Dies führt jedoch notwendigerweise eine Laufzeitprüfung durch, um festzustellen, ob das tatsächlich betroffene Objekt vom richtigen Typ ist.
Einmal erstellt, kann der Typ eines Objekts nicht mehr geändert werden (nicht zuletzt hat er möglicherweise nicht dieselbe Größe). Sie können jedoch eine Instanz konvertieren und eine neue Instanz des zweiten Typs erstellen. Sie müssen den Konvertierungscode jedoch manuell schreiben.
Nein, das ist nicht möglich.
Stellen Sie sich ein Szenario vor, in dem ein ACBus eine abgeleitete Klasse der Basisklasse Bus ist. ACBus verfügt über Funktionen wie TurnOnAC und TurnOffAC, die in einem Feld namens ACState ausgeführt werden. TurnOnAC setzt ACState ein und TurnOffAC setzt ACState aus. Wenn Sie versuchen, TurnOnAC- und TurnOffAC-Funktionen auf Bus zu verwenden, macht dies keinen Sinn.
class Program
{
static void Main(string[] args)
{
a a1 = new b();
a1.print();
}
}
class a
{
public a()
{
Console.WriteLine("base class object initiated");
}
public void print()
{
Console.WriteLine("base");
}
}
class b:a
{
public b()
{
Console.WriteLine("child class object");
}
public void print1()
{
Console.WriteLine("derived");
}
}
}}
Wenn wir ein untergeordnetes Klassenobjekt erstellen, wird das Basisklassenobjekt automatisch initiiert, sodass die Referenzvariable der Basisklasse auf das untergeordnete Klassenobjekt verweisen kann.
aber nicht umgekehrt, da eine untergeordnete Klassenreferenzvariable nicht auf das Basisklassenobjekt verweisen kann, da kein untergeordnetes Klassenobjekt erstellt wird.
Beachten Sie auch, dass die Referenzvariable der Basisklasse nur Basisklassenmitglieder aufrufen kann.
Es gibt tatsächlich einen Weg, dies zu tun. Überlegen Sie, wie Sie Newtonsoft JSON verwenden können, um ein Objekt von json zu deserialisieren. Fehlende Elemente werden (oder können es zumindest) ignoriert und alle ihm bekannten Elemente ausgefüllt.
Also hier ist, wie ich es gemacht habe. Ein kleines Codebeispiel folgt meiner Erklärung.
Erstellen Sie eine Instanz Ihres Objekts aus der Basisklasse und füllen Sie sie entsprechend aus.
Serialisieren Sie dieses Objekt mithilfe der "jsonconvert" -Klasse von Newtonsoft json in eine json-Zeichenfolge.
Erstellen Sie nun Ihr Unterklassenobjekt, indem Sie es mit der in Schritt 2 erstellten JSON-Zeichenfolge deserialisieren. Dadurch wird eine Instanz Ihrer Unterklasse mit allen Eigenschaften der Basisklasse erstellt.
Das funktioniert wie ein Zauber! Also .. wann ist das nützlich? Einige Leute fragten, wann dies sinnvoll wäre, und schlugen vor, das OP-Schema zu ändern, um der Tatsache Rechnung zu tragen, dass dies mit Klassenvererbung (in .Net) nicht nativ möglich ist.
In meinem Fall habe ich eine Einstellungsklasse, die alle "Basis" -Einstellungen für einen Dienst enthält. Bestimmte Dienste verfügen über mehr Optionen und diese stammen aus einer anderen DB-Tabelle, sodass diese Klassen die Basisklasse erben. Sie haben alle unterschiedliche Optionen. Wenn Sie also die Daten für einen Dienst abrufen, ist es viel einfacher, die Werte ZUERST mit einer Instanz des Basisobjekts zu füllen. Eine Methode, um dies mit einer einzelnen DB-Abfrage zu tun. Gleich danach erstelle ich das Unterklassenobjekt mit der oben beschriebenen Methode. Ich mache dann eine zweite Abfrage und fülle alle dynamischen Werte auf dem Unterklassenobjekt.
Die endgültige Ausgabe ist eine abgeleitete Klasse mit allen festgelegten Optionen. Wenn Sie dies für weitere neue Unterklassen wiederholen, sind nur wenige Codezeilen erforderlich. Es ist einfach und verwendet ein sehr bewährtes Paket (Newtonsoft), damit die Magie funktioniert.
Dieser Beispielcode lautet vb.Net, Sie können ihn jedoch problemlos in c # konvertieren.
' First, create the base settings object.
Dim basePMSettngs As gtmaPayMethodSettings = gtmaPayments.getBasePayMethodSetting(payTypeId, account_id)
Dim basePMSettingsJson As String = JsonConvert.SerializeObject(basePMSettngs, Formatting.Indented)
' Create a pmSettings object of this specific type of payment and inherit from the base class object
Dim pmSettings As gtmaPayMethodAimACHSettings = JsonConvert.DeserializeObject(Of gtmaPayMethodAimACHSettings)(basePMSettingsJson)
var destObject = JsonConvert.DeserializeObject<DestinationType>(JsonConvert.SerializeObject(srcObject));
. Ich würde dies nur für Unit-Tests und andere nicht produktive "Hacking" verwenden!
Könnte nicht relevant sein, aber ich konnte aufgrund seiner Basis Code für ein abgeleitetes Objekt ausführen. Es ist definitiv hackiger als ich es gerne hätte, aber es funktioniert:
public static T Cast<T>(object obj)
{
return (T)obj;
}
...
//Invoke parent object's json function
MethodInfo castMethod = this.GetType().GetMethod("Cast").MakeGenericMethod(baseObj.GetType());
object castedObject = castMethod.Invoke(null, new object[] { baseObj });
MethodInfo jsonMethod = baseObj.GetType ().GetMethod ("ToJSON");
return (string)jsonMethod.Invoke (castedObject,null);
Sie können dies mit generischen tun.
public class BaseClass
{
public int A { get; set; }
public int B { get; set; }
private T ConvertTo<T>() where T : BaseClass, new()
{
return new T
{
A = A,
B = B
}
}
public DerivedClass1 ConvertToDerivedClass1()
{
return ConvertTo<DerivedClass1>();
}
public DerivedClass2 ConvertToDerivedClass2()
{
return ConvertTo<DerivedClass2>();
}
}
public class DerivedClass1 : BaseClass
{
public int C { get; set; }
}
public class DerivedClass2 : BaseClass
{
public int D { get; set; }
}
Mit diesem Ansatz erhalten Sie drei Vorteile.
Sie können eine Erweiterung verwenden:
public static void CopyOnlyEqualProperties<T>(this T objDest, object objSource) where T : class
{
foreach (PropertyInfo propInfo in typeof(T).GetProperties())
if (objSource.GetType().GetProperties().Any(z => z.Name == propInfo.Name && z.GetType() == propInfo.GetType()))
propInfo.SetValue(objDest, objSource.GetType().GetProperties().First(z => z.Name == propInfo.Name && z.GetType() == propInfo.GetType()).GetValue(objSource));
}
In Code:
public class BaseClass
{
public string test{ get; set;}
}
public Derived : BaseClass
{
//Some properies
}
public void CopyProps()
{
BaseClass baseCl =new BaseClass();
baseCl.test="Hello";
Derived drv=new Derived();
drv.CopyOnlyEqualProperties(baseCl);
//Should return Hello to the console now in derived class.
Console.WriteLine(drv.test);
}
Ich weiß, dass dies alt ist, aber ich habe es eine ganze Weile erfolgreich verwendet.
private void PopulateDerivedFromBase<TB,TD>(TB baseclass,TD derivedclass)
{
//get our baseclass properties
var bprops = baseclass.GetType().GetProperties();
foreach (var bprop in bprops)
{
//get the corresponding property in the derived class
var dprop = derivedclass.GetType().GetProperty(bprop.Name);
//if the derived property exists and it's writable, set the value
if (dprop != null && dprop.CanWrite)
dprop.SetValue(derivedclass,bprop.GetValue(baseclass, null),null);
}
}
Ich habe einige Teile der vorherigen Antworten (dank dieser Autoren) kombiniert und eine einfache statische Klasse mit zwei Methoden zusammengestellt, die wir verwenden.
Ja, es ist einfach, nein, es deckt nicht alle Szenarien ab, ja, es könnte erweitert und verbessert werden, nein, es ist nicht perfekt, ja, es könnte möglicherweise effizienter gemacht werden, nein, es ist nicht das Beste seit geschnittenem Brot, ja, es gibt Vollständige robuste Nuget-Paket-Objekt-Mapper da draußen, die viel besser für den intensiven Gebrauch geeignet sind, usw. usw., yada yada - aber es funktioniert für unsere Grundbedürfnisse :)
Und natürlich wird versucht, Werte von jedem Objekt auf jedes abgeleitete oder nicht abgeleitete Objekt abzubilden (nur die öffentlichen Eigenschaften, die natürlich den gleichen Namen haben - ignorieren den Rest).
VERWENDUNG:
SesameStreetCharacter puppet = new SesameStreetCharacter() { Name = "Elmo", Age = 5 };
// creates new object of type "RealPerson" and assigns any matching property
// values from the puppet object
// (this method requires that "RealPerson" have a parameterless constructor )
RealPerson person = ObjectMapper.MapToNewObject<RealPerson>(puppet);
// OR
// create the person object on our own
// (so RealPerson can have any constructor type that it wants)
SesameStreetCharacter puppet = new SesameStreetCharacter() { Name = "Elmo", Age = 5 };
RealPerson person = new RealPerson("tall") {Name = "Steve"};
// maps and overwrites any matching property values from
// the puppet object to the person object so now our person's age will get set to 5 and
// the name "Steve" will get overwritten with "Elmo" in this example
ObjectMapper.MapToExistingObject(puppet, person);
STATIC UTILITY CLASS:
public static class ObjectMapper
{
// the target object is created on the fly and the target type
// must have a parameterless constructor (either compiler-generated or explicit)
public static Ttarget MapToNewObject<Ttarget>(object sourceobject) where Ttarget : new()
{
// create an instance of the target class
Ttarget targetobject = (Ttarget)Activator.CreateInstance(typeof(Ttarget));
// map the source properties to the target object
MapToExistingObject(sourceobject, targetobject);
return targetobject;
}
// the target object is created beforehand and passed in
public static void MapToExistingObject(object sourceobject, object targetobject)
{
// get the list of properties available in source class
var sourceproperties = sourceobject.GetType().GetProperties().ToList();
// loop through source object properties
sourceproperties.ForEach(sourceproperty => {
var targetProp = targetobject.GetType().GetProperty(sourceproperty.Name);
// check whether that property is present in target class and is writeable
if (targetProp != null && targetProp.CanWrite)
{
// if present get the value and map it
var value = sourceobject.GetType().GetProperty(sourceproperty.Name).GetValue(sourceobject, null);
targetobject.GetType().GetProperty(sourceproperty.Name).SetValue(targetobject, value, null);
}
});
}
}
Sie können einen Kopierkonstruktor verwenden, der den Instanzkonstruktor sofort aufruft, oder wenn Ihr Instanzkonstruktor mehr als Zuweisungen ausführt, muss der Kopierkonstruktor der Instanz die eingehenden Werte zuweisen.
class Person
{
// Copy constructor
public Person(Person previousPerson)
{
Name = previousPerson.Name;
Age = previousPerson.Age;
}
// Copy constructor calls the instance constructor.
public Person(Person previousPerson)
: this(previousPerson.Name, previousPerson.Age)
{
}
// Instance constructor.
public Person(string name, int age)
{
Name = name;
Age = age;
}
public int Age { get; set; }
public string Name { get; set; }
}
In diesem Beispiel wurde auf die Microsoft C # -Dokumentation unter Konstruktor verwiesen, da dieses Problem in der Vergangenheit aufgetreten war.
Eine andere Lösung besteht darin, eine Erweiterungsmethode wie folgt hinzuzufügen:
public static void CopyProperties(this object destinationObject, object sourceObject, bool overwriteAll = true)
{
try
{
if (sourceObject != null)
{
PropertyInfo[] sourceProps = sourceObject.GetType().GetProperties();
List<string> sourcePropNames = sourceProps.Select(p => p.Name).ToList();
foreach (PropertyInfo pi in destinationObject.GetType().GetProperties())
{
if (sourcePropNames.Contains(pi.Name))
{
PropertyInfo sourceProp = sourceProps.First(srcProp => srcProp.Name == pi.Name);
if (sourceProp.PropertyType == pi.PropertyType)
if (overwriteAll || pi.GetValue(destinationObject, null) == null)
{
pi.SetValue(destinationObject, sourceProp.GetValue(sourceObject, null), null);
}
}
}
}
}
catch (ApplicationException ex)
{
throw;
}
}
Dann haben Sie einen Konstruktor in jeder abgeleiteten Klasse, der die Basisklasse akzeptiert:
public class DerivedClass: BaseClass
{
public DerivedClass(BaseClass baseModel)
{
this.CopyProperties(baseModel);
}
}
Optional werden auch Zieleigenschaften überschrieben, wenn diese bereits festgelegt sind (nicht null) oder nicht.
Ist es möglich, einer abgeleiteten Klassenreferenz ein Basisklassenobjekt mit einer expliziten Typumwandlung in C # zuzuweisen?
Es sind nicht nur explizite, sondern auch implizite Konvertierungen möglich.
Die C # -Sprache erlaubt solche Konvertierungsoperatoren nicht, aber Sie können sie trotzdem mit reinem C # schreiben und sie funktionieren. Beachten Sie, dass die Klasse, die den impliziten Konvertierungsoperator ( Derived
) definiert, und die Klasse, die den Operator ( Program
) verwendet, in separaten Assemblys definiert werden müssen (z. B. befindet sich die Derived
Klasse in einer, auf library.dll
die durch das program.exe
Enthalten der Program
Klasse verwiesen wird ).
//In library.dll:
public class Base { }
public class Derived {
[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Implicit(Base a) {
return new Derived(a); //Write some Base -> Derived conversion code here
}
[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Explicit(Base a) {
return new Derived(a); //Write some Base -> Derived conversion code here
}
}
//In program.exe:
class Program {
static void Main(string[] args) {
Derived z = new Base(); //Visual Studio can show squiggles here, but it compiles just fine.
}
}
Wenn Sie mithilfe der Projektreferenz in Visual Studio auf die Bibliothek verweisen, zeigt VS bei Verwendung der impliziten Konvertierung Kringel an, die jedoch problemlos kompiliert werden können. Wenn Sie nur auf die verweisen library.dll
, gibt es keine Kringel.
System.Runtime.CompilerServices.SpecialName
Attribute? Die Dokumente für jede Version von der frühesten verfügbaren (2.0) bis zur "aktuellen Version" (4.6? "Jemand? Jemand?") Sagen nicht, was sie tun, sondern "Die SpecialNameAttribute-Klasse wird derzeit in .NET nicht verwendet Framework, ist aber für die zukünftige Verwendung reserviert. " Siehe: [Link] ( msdn.microsoft.com/en-us/library/ms146064(v=vs.100).aspx ).
where T : Delegate
oder parametrisierte Eigenschaften, auch bekannt als Indexer usw. usw. usw.).
what does System.Runtime.CompilerServices.SpecialName Attribute do?
- Es wird verwendet, um die Methoden zu markieren, die von einigen speziellen Convenience-Konstrukten der übergeordneten .Net-Sprachen erzeugt werden: Eigenschaftszugriffsberechtigte, Ereigniszugriffsberechtigte, Konstruktoren, Operatoren, Indexer usw. Wenn die IL-Methode nicht mit gekennzeichnet ist, wird specialname
sie nicht angezeigt als Eigenschaft / Ereignis / Konstruktor und es würde nur als normale Methode erkannt werden. Das manuelle Markieren von Methoden mit entsprechendem Namen mit diesem Attribut erledigt nur manuell einen Teil der Arbeit des Compilers.
op_Exponent
Methode und markieren Sie sie mit dem specialname
Attribut.
Wie wäre es mit:
public static T As<T>(this object obj)
{
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(obj));
}
Der beste Weg, um alle Basiseigenschaften zum abgeleiteten Element hinzuzufügen, ist die Verwendung der Reflektion im Costructor. Probieren Sie diesen Code aus, ohne Methoden oder Instanzen zu erstellen.
public Derived(Base item) :base()
{
Type type = item.GetType();
System.Reflection.PropertyInfo[] properties = type.GetProperties();
foreach (var property in properties)
{
try
{
property.SetValue(this, property.GetValue(item, null), null);
}
catch (Exception) { }
}
}
Ich bin nicht der Meinung, dass dies nicht möglich ist. Sie können es so machen:
public class Auto
{
public string Make {get; set;}
public string Model {get; set;}
}
public class Sedan : Auto
{
public int NumberOfDoors {get; set;}
}
public static T ConvertAuto<T>(Sedan sedan) where T : class
{
object auto = sedan;
return (T)loc;
}
Verwendung:
var sedan = new Sedan();
sedan.NumberOfDoors = 4;
var auto = ConvertAuto<Auto>(sedan);
var auto =
ist immer noch vom Typsedan
So habe ich das für Felder gelöst. Sie können dieselbe Iteration über Eigenschaften durchführen, wenn Sie möchten. Möglicherweise möchten Sie einige Überprüfungen für null
usw. durchführen, aber dies ist die Idee.
public static DerivedClass ConvertFromBaseToDerived<BaseClass, DerivedClass>(BaseClass baseClass)
where BaseClass : class, new()
where DerivedClass : class, BaseClass, new()
{
DerivedClass derived = (DerivedClass)Activator.CreateInstance(typeof(DerivedClass));
derived.GetType().GetFields().ToList().ForEach(field =>
{
var base_ = baseClass.GetType().GetField(field.Name).GetValue(baseClass);
field.SetValue(derived, base_);
});
return derived;
}
Sie können das Basisobjekt einfach in JSON serialisieren und dann in das abgeleitete Objekt deserialisieren.
Nein, siehe diese Frage, die ich gestellt habe - Upcasting in .NET mit Generika
Der beste Weg ist, einen Standardkonstruktor für die Klasse zu erstellen, eine Initialise
Methode zu konstruieren und dann aufzurufen
Nicht im traditionellen Sinne ... Konvertieren Sie zu Json, dann zu Ihrem Objekt und boomen Sie, fertig! Jesse oben hatte die Antwort zuerst gepostet, aber nicht diese Erweiterungsmethoden verwendet, die den Prozess so viel einfacher machen. Erstellen Sie einige Erweiterungsmethoden:
public static string ConvertToJson<T>(this T obj)
{
return JsonConvert.SerializeObject(obj);
}
public static T ConvertToObject<T>(this string json)
{
if (string.IsNullOrEmpty(json))
{
return Activator.CreateInstance<T>();
}
return JsonConvert.DeserializeObject<T>(json);
}
Legen Sie sie für immer in Ihre Toolbox, dann können Sie dies immer tun:
var derivedClass = baseClass.ConvertToJson().ConvertToObject<derivedClass>();
Ah, die Macht von JSON.
Es gibt ein paar Fallstricke bei diesem Ansatz: 1. Wir erstellen wirklich ein neues Objekt, kein Casting, was wichtig sein kann oder nicht. Private Felder werden nicht übertragen, Konstruktoren mit Parametern werden nicht aufgerufen usw. Wenn unsere Klasse jedoch nicht auf privaten Feldern und Konstruktoren basiert, ist dies eine sehr effektive Methode, um Daten von Klasse zu Klasse zu verschieben, ohne sie zuzuordnen und aufzurufen Konstruktoren, was der Hauptgrund ist, warum wir überhaupt gießen wollen.