C # 'da açık bir typecast ile türetilmiş bir sınıf referansına temel bir sınıf nesnesi atamak mümkün müdür ?.
Denedim ve bir çalışma zamanı hatası oluşturuyor.
C # 'da açık bir typecast ile türetilmiş bir sınıf referansına temel bir sınıf nesnesi atamak mümkün müdür ?.
Denedim ve bir çalışma zamanı hatası oluşturuyor.
Yanıtlar:
Hayır. Türetilmiş bir sınıfa yapılan başvuru, aslında türetilmiş sınıfın (veya null) bir örneğine başvurmalıdır. Aksi takdirde nasıl davranmasını beklersiniz?
Örneğin:
object o = new object();
string s = (string) o;
int i = s.Length; // What can this sensibly do?
Temel türün bir örneğini türetilmiş türe dönüştürebilmek istiyorsanız, uygun bir türetilmiş tür örneği oluşturmak için bir yöntem yazmanızı öneririm. Veya miras ağacınıza tekrar bakın ve yeniden tasarlamaya çalışın, böylece ilk etapta bunu yapmanıza gerek kalmaz.
Derived
, ancak bir Derived
referansı referans olarak değerlendirebilirsiniz Base
.
Base
, diğeri örneğini oluşturuyor Derived
. Üzerine b
geçersiz kılınan bir sanal yöntemi çağırırsanız Derived
, Derived
örneğiniz varsa davranışı görürsünüz Derived
. Ancak bir Stack Overflow yorum dizisindeki ayrıntılara girmek gerçekten uygun değildir - bu oldukça temel bir konu olduğu için gerçekten iyi bir C # kitabı veya öğretici okumalısınız.
Hayır, bunu türetilmiş bir sınıf referansına atamak, "Temel sınıf türetilmiş sınıfın tam olarak ikame edilmesidir, türetilmiş sınıfın yapabildiği her şeyi yapabilir" demek gibi olacağından bu mümkün değildir, bu da genel olarak türetilmiş sınıflar sunduğundan bu doğru değildir temel sınıflarından daha fazla işlevsellik (en azından kalıtımın arkasındaki fikir budur).
Türetilmiş sınıfta, değerleri kopyalayarak bir temel sınıf nesnesini parametre olarak alan bir yapıcı yazabilirsiniz.
Bunun gibi bir şey:
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
}
}
Bu durumda, temel nesneyi kopyalar ve türetilmiş üyeler için varsayılan değerlere sahip tamamen işlevsel bir türetilmiş sınıf nesnesi alırsınız. Bu şekilde Jon Skeet'in işaret ettiği problemden de kurtulabilirsiniz:
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!
Bu sorunu yaşadım ve bir tür parametresi alan ve mevcut nesneyi bu türe dönüştüren bir yöntem ekleyerek çözdüm.
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;
}
Bu, kodunuzda şu şekilde kullanabileceğiniz anlamına gelir:
var base = new Base();
base.Data = 1;
var derived = base.As<Derived>();
Console.Write(derived.Data); // Would output 1
Diğerlerinin cevapladığı gibi, Hayır.
Türetilmiş bir tür olarak bir temel türü kullanmam gerektiğinde, bu talihsiz durumlarda aşağıdaki kodu kullanıyorum. Evet, bu Liskov İkame İlkesinin (LSP) ihlalidir ve evet çoğu zaman miras yerine kompozisyonu tercih ederiz. Orijinal cevabına dayanan Markus Knappen Johansson'a destek.
Temel sınıftaki bu kod:
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;
}
Şunları sağlar:
derivedObject = baseObect.As<derivedType>()
Yansıma kullandığı için "pahalıdır". Buna göre kullanın.
user-defined conversions to or from a base class are not allowed
Bunun nedenlerini görüyorum ama hayal kırıklığına uğradım, buna izin verseydi çok eğlenceli olurdu ..
if (type.BaseType != null)
Markus Knappen Johansson'un A'sına göre Beyanı eklediğinizi fark ettim . Neden bu? Bu, MyBaseClass'tan (veya bu konuyla ilgili herhangi bir şeyden) Türetilmeyen Çağrılarda bir Türe izin vereceği anlamına gelir. MyDerivedObject'e atanırsa yine de bir derleyici hatasına neden olacağının farkındayım, ancak sadece bir İfade olarak kullanılıyorsa, derlenecek ve çalışma zamanında "myBaseObject" den herhangi bir veri kopyalanmadan bir myDerivedObject oluşturacaktır. Bunun için bir kullanım durumu düşünemiyorum.
Bugün aynı sorunla karşılaştım ve kullanarak soruna basit ve hızlı bir çözüm buldum JsonConvert
.
var base = new BaseClass();
var json = JsonConvert.SerializeObject(base);
DerivedClass derived = JsonConvert.DeserializeObject<DerivedClass>(json);
Buradaki herkesin dediği gibi, bu doğrudan mümkün değil.
Tercih ettiğim ve oldukça temiz olan yöntem AutoMapper gibi bir Object Mapper kullanmaktır .
Özelliklerin bir örnekten diğerine (aynı tip olması gerekmez) otomatik olarak kopyalanması görevini yerine getirir.
@ Ybo'nun cevabını genişletmek - bu mümkün değildir, çünkü temel sınıfın sahip olduğunuz örneği aslında türetilmiş sınıfın bir örneği değildir. Yalnızca temel sınıfın üyelerini bilir ve türetilmiş sınıfın üyeleri hakkında hiçbir şey bilmez.
Türetilmiş sınıfın bir örneğini temel sınıfın bir örneğine dönüştürebilmenizin nedeni, türetilmiş sınıfın aslında zaten bu üyelere sahip olduğundan temel sınıfın bir örneği olmasıdır. Bunun tersi söylenemez.
Temel sınıf olarak yazılan bir değişkeni türetilmiş bir sınıfın türüne çevirebilirsiniz ; ancak, zorunlu olarak bu, ilgili gerçek nesnenin doğru türde olup olmadığını görmek için bir çalışma zamanı kontrolü yapacaktır.
Oluşturulduktan sonra , bir nesnenin türü değiştirilemez (en önemlisi, aynı boyutta olmayabilir). Bununla birlikte, ikinci türün yeni bir örneğini oluşturarak bir örneği dönüştürebilirsiniz - ancak dönüştürme kodunu manuel olarak yazmanız gerekir.
Hayır, bu mümkün değil.
Bir ACBus'un türetilmiş bir temel sınıf veri yolu olduğu bir senaryo düşünün. ACBus, ACState adlı bir alanda çalışan TurnOnAC ve TurnOffAC gibi özelliklere sahiptir. TurnOnAC, ACState'i açık olarak ayarlar ve TurnOffAC, ACState'i kapalı olarak ayarlar. Veriyolunda TurnOnAC ve TurnOffAC özelliklerini kullanmaya çalışırsanız, bu bir anlam ifade etmiyor.
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");
}
}
}
Bir alt sınıf nesnesi oluşturduğumuzda, temel sınıf nesnesi otomatik olarak başlatılır, böylece temel sınıf başvurusu değişkeni alt sınıf nesnesine işaret edebilir.
ancak bunun tersi olmaz çünkü bir alt sınıf referans değişkeni temel sınıf nesnesine işaret edemez çünkü hiçbir alt sınıf nesnesi oluşturulmaz.
ve ayrıca temel sınıf referans değişkeninin yalnızca temel sınıf üyesini çağırabileceğine dikkat edin.
Aslında bunu yapmanın bir yolu var. Bir nesneyi json'dan seri durumdan çıkarmak için Newtonsoft JSON'u nasıl kullanabileceğinizi düşünün. Eksik öğeleri görmezden gelir (veya en azından yapabilir) ve bildiği tüm öğeleri doldurur.
İşte bunu nasıl yaptım. Küçük bir kod örneği açıklamamı takip edecek.
Temel sınıftan nesnenizin bir örneğini oluşturun ve buna göre doldurun.
Newtonsoft json'un "jsonconvert" sınıfını kullanarak, bu nesneyi bir json dizesine serileştirin.
Şimdi, 2. adımda oluşturulan json dizesi ile seriyi kaldırarak alt sınıf nesnenizi oluşturun. Bu, alt sınıfınızın temel sınıfın tüm özelliklerine sahip bir örneğini oluşturacaktır.
Bu bir cazibe gibi çalışıyor! Peki .. bu ne zaman yararlıdır? Bazı insanlar bunun ne zaman mantıklı olacağını sordu ve bunu sınıf kalıtımıyla (.Net'te) yerel olarak yapamayacağınız gerçeğine uyum sağlamak için OP'nin şemasını değiştirmeyi önerdiler.
Benim durumumda, bir hizmet için tüm "temel" ayarları içeren bir ayarlar sınıfım var. Belirli hizmetlerin daha fazla seçeneği vardır ve bunlar farklı bir DB tablosundan gelir, bu nedenle bu sınıflar temel sınıfı miras alır. Hepsinin farklı seçenekleri vardır. Dolayısıyla, bir hizmet için verileri alırken, değerleri İLK olarak, temel nesnenin bir örneğini kullanarak doldurmak çok daha kolaydır. Bunu tek bir DB sorgusuyla yapmak için bir yöntem. Hemen ardından alt sınıf nesnesini yukarıda anlattığım yöntemi kullanarak oluşturuyorum. Daha sonra ikinci bir sorgu yapıyorum ve alt sınıf nesnesindeki tüm dinamik değerleri dolduruyorum.
Son çıktı, tüm seçeneklerin ayarlandığı türetilmiş bir sınıftır. Ek yeni alt sınıflar için bunu tekrarlamak yalnızca birkaç satır kod gerektirir. Çok basit ve sihrin çalışması için çok denenmiş ve test edilmiş bir paket (Newtonsoft) kullanıyor.
Bu örnek kod vb.Net'tir, ancak kolayca c # koduna dönüştürebilirsiniz.
' 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));
. Bunu yalnızca birim testleri ve diğer üretim dışı "hackleme" için kullanırım!
Bir Uzantı kullanabilirsiniz:
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));
}
Kodda:
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);
}
Alakalı olmayabilir, ancak kodu tabanına göre türetilmiş bir nesnede çalıştırabildim. Kesinlikle istediğimden daha karmaşık ama işe yarıyor:
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);
Bunu jenerik kullanarak yapabilirsiniz.
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; }
}
Bu yaklaşımı kullanarak üç avantaj elde edersiniz.
Bunun eski olduğunu biliyorum ama bunu bir süredir başarıyla kullandım.
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);
}
}
Önceki cevapların bazı kısımlarını birleştirdim (bu yazarlar sayesinde) ve kullandığımız iki yöntemle basit bir statik sınıf oluşturdum.
Evet, basit, hayır tüm senaryoları kapsamıyor, evet genişletilebilir ve daha iyi hale getirilebilir, hayır mükemmel değil, evet muhtemelen daha verimli hale getirilebilir, hayır dilimlenmiş ekmekten bu yana en iyi şey değil, evet var yoğun kullanım için çok daha iyi olan tam kapsamlı nuget paketi nesne eşleyicileri, vb. yada yada - ama yine de temel ihtiyaçlarımız için çalışıyor :)
Ve elbette, herhangi bir nesneden türetilmiş olsun ya da olmasın herhangi bir nesneye değerleri eşlemeye çalışacaktır (tabii ki sadece aynı adı verilen genel özellikler - geri kalanını göz ardı eder).
KULLANIM:
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);
STATİK KULLANIM SINIFI:
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);
}
});
}
}
Örnek oluşturucuyu hemen çağıran bir kopya yapıcısı kullanabilirsiniz veya örnek oluşturucunuz atamalardan fazlasını yapıyorsa, kopya yapıcısının gelen değerleri örneğe atamasını sağlayabilirsiniz.
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; }
}
Geçmişte bu sorunu yaşamış olan bu örnek için Oluşturucu altındaki Microsoft C # Belgelerine başvurulmuştur .
Diğer bir çözüm ise şöyle bir uzantı yöntemi eklemektir:
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;
}
}
daha sonra her türetilmiş sınıfta temel sınıfı kabul eden bir kurucuya sahip olun:
public class DerivedClass: BaseClass
{
public DerivedClass(BaseClass baseModel)
{
this.CopyProperties(baseModel);
}
}
Ayrıca, önceden ayarlanmışsa (boş değilse) isteğe bağlı olarak hedef özelliklerin üzerine yazacaktır.
C # 'da açık bir typecast ile türetilmiş bir sınıf referansına temel bir sınıf nesnesi atamak mümkün müdür ?.
Yalnızca açık değil, aynı zamanda örtük dönüşümler de mümkündür.
C # dili, bu tür dönüştürme işleçlerine izin vermez, ancak bunları yine de saf C # kullanarak yazabilirsiniz ve çalışırlar. Örtük dönüştürme işlecini ( Derived
) tanımlayan sınıf ve ( ) işlecini kullanan sınıfın Program
ayrı derlemelerde tanımlanması gerektiğine dikkat edin (örneğin, Derived
sınıf, sınıfı içererek library.dll
başvurulan a içindedir).program.exe
Program
//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.
}
}
Visual Studio'da Proje Başvurusunu kullanarak kitaplığa başvurduğunuzda, VS, örtük dönüştürmeyi kullandığınızda dalgalı çizgiler gösterir, ancak yalnızca iyi derler. Sadece referans verirseniz library.dll
, dalgalı çizgiler yoktur.
System.Runtime.CompilerServices.SpecialName
Öznitelik ne yapar ? Kullanılabilir en eski sürümden (2.0) "geçerli sürüme" (4.6? "Kimse mi? Kimse mi?") Kadar her sürümün dokümanları ne yaptığını söylemiyor, ancak "SpecialNameAttribute sınıfı şu anda .NET'te kullanılmıyor Çerçeve, ancak gelecekteki kullanım için ayrılmıştır. ". Bakınız: [bağlantı] ( msdn.microsoft.com/en-us/library/ms146064(v=vs.100).aspx ).
where T : Delegate
veya parametreleştirilmiş özellikler, yani indeksleyiciler vb.).
what does System.Runtime.CompilerServices.SpecialName Attribute do?
- Üst düzey .Net dillerinin bazı özel kolaylık yapıları tarafından üretilen yöntemleri işaretlemek için kullanılır: özellik erişimcileri, olay erişimcileri, kurucular, operatörler, indeksleyiciler vb. IL yöntemi ile işaretlenmedikçe specialname
görülmez. özellik / olay / yapıcı olarak ve normal bir yöntem olarak kabul edilecektir. Uygun şekilde adlandırılmış yöntemleri bu öznitelikle manuel olarak işaretlemek, derleyicinin işinin bir kısmını elle yapmaktır.
op_Exponent
yöntem tanımlayın ve onu specialname
öznitelikle işaretleyin .
Peki ya:
public static T As<T>(this object obj)
{
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(obj));
}
Türetilmiş öğeye tüm temel özellikleri eklemenin en iyi yolu, oluşturucudaki yansımayı kullanmaktır. Yöntemler veya örnekler oluşturmadan bu kodu deneyin.
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) { }
}
}
Bunun mümkün olmadığına katılmıyorum. Bunu şu şekilde yapabilirsiniz:
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;
}
Kullanım:
var sedan = new Sedan();
sedan.NumberOfDoors = 4;
var auto = ConvertAuto<Auto>(sedan);
var auto =
hala tiptesedan
Bunu tarlalar için böyle çözdüm. İsterseniz aynı yinelemeyi özellikler aracılığıyla da yapabilirsiniz. null
Vb için bazı kontroller yapmak isteyebilirsiniz ama fikir bu.
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;
}
Temel nesneyi JSON'a serileştirebilir ve ardından türetilmiş nesneye serisini kaldırabilirsiniz.
Geleneksel anlamda değil ... Json'a, sonra nesnenize dönüştürün ve boom, tamam! Yukarıdaki Jesse cevabı önce yayınladı, ancak süreci çok daha kolay hale getiren bu uzatma yöntemlerini kullanmadı. Birkaç uzatma yöntemi oluşturun:
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);
}
Onları sonsuza kadar alet kutunuza koyun, sonra bunu her zaman yapabilirsiniz:
var derivedClass = baseClass.ConvertToJson().ConvertToObject<derivedClass>();
Ah, JSON'un gücü.
Bu yaklaşımla ilgili birkaç ipucu var: Gerçekten yeni bir nesne yaratıyoruz, döküm değil, önemli olabilir veya olmayabilir. Özel alanlar aktarılmayacak, parametrelere sahip kurucular çağrılmayacak, vb. Bazı alt jsonların atanmaması mümkündür. Akışlar doğuştan JsonConvert tarafından işlenmez. Bununla birlikte, sınıfımız özel alanlara ve kuruculara güvenmiyorsa, bu, verileri eşleme yapmadan ve kurucuları çağırmadan sınıftan sınıfa taşımak için çok etkili bir yöntemdir, bu da ilk etapta döküm yapmak istememizin ana nedenidir.
Hayır, sorduğum soruya bakın - jenerik kullanarak .NET'te güncelleme
En iyi yol, sınıf üzerinde varsayılan bir kurucu yapmak, oluşturmak ve ardından bir Initialise
yöntemi çağırmaktır.