C# : Converting Base Class to Child Class - c#

I have a class, NetworkClient as a base class :
using System.IO;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace Network
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class NetworkClient
{
public NetworkClient()
{
tcpClient = new TcpClient();
}
public NetworkClient(TcpClient client)
{
tcpClient = client;
}
public virtual bool IsConnected
{
get;
private set;
}
private StreamWriter writer { get; set; }
private StreamReader reader { get; set; }
private TcpClient tcpClient
{
get;
set;
}
public virtual NetworkServerInfo NetworkServerInfo
{
get;
set;
}
public async virtual void Connect(NetworkServerInfo info)
{
if (tcpClient == null)
{
tcpClient=new TcpClient();
}
await tcpClient.ConnectAsync(info.Address,info.Port);
reader = new StreamReader(tcpClient.GetStream());
writer = new StreamWriter(tcpClient.GetStream());
}
public virtual void Disconnect()
{
tcpClient.Close();
reader.Dispose();
writer.Dispose();
}
public async virtual void Send(string data)
{
await writer.WriteLineAsync(data);
}
public async virtual Task<string> Receive()
{
return await reader.ReadLineAsync();
}
}
}
And also have a child class derived from NetworkClient :
using System.Net;
namespace Network
{
using Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class SkyfilterClient : NetworkClient
{
public virtual IPAddress Address
{
get;
set;
}
public virtual int Port
{
get;
set;
}
public virtual string SessionID
{
get;
set;
}
public virtual User UserData
{
get;
set;
}
protected virtual bool Authenticate(string username, string password)
{
throw new System.NotImplementedException();
}
}
}
The problem is, that when im trying to cast NetworkClient into SkyfilterClient. An exception is thrown, Unable to cast object of type 'Network.NetworkClient' to type 'Network.SkyfilterClient'.
Whats wrong with my code ? I see that Stream can be converted to NetworkStream, MemoryStream. Why NetworkClient can't be converted to Skyfilter Client?

As long as the object is actually a SkyfilterClient, then a cast should work. Here is a contrived example to prove this:
using System;
class Program
{
static void Main()
{
NetworkClient net = new SkyfilterClient();
var sky = (SkyfilterClient)net;
}
}
public class NetworkClient{}
public class SkyfilterClient : NetworkClient{}
However, if it is actually a NetworkClient, then you cannot magically make it become the subclass. Here is an example of that:
using System;
class Program
{
static void Main()
{
NetworkClient net = new NetworkClient();
var sky = (SkyfilterClient)net;
}
}
public class NetworkClient{}
public class SkyfilterClient : NetworkClient{}
HOWEVER, you could create a converter class. Here is an example of that, also:
using System;
class Program
{
static void Main()
{
NetworkClient net = new NetworkClient();
var sky = SkyFilterClient.CopyToSkyfilterClient(net);
}
}
public class NetworkClient
{
public int SomeVal {get;set;}
}
public class SkyfilterClient : NetworkClient
{
public int NewSomeVal {get;set;}
public static SkyfilterClient CopyToSkyfilterClient(NetworkClient networkClient)
{
return new SkyfilterClient{NewSomeVal = networkClient.SomeVal};
}
}
But, keep in mind that there is a reason you cannot convert this way. You may be missing key information that the subclass needs.
Finally, if you just want to see if the attempted cast will work, then you can use is:
if(client is SkyfilterClient)
cast

I'm surprised AutoMapper hasn't come up as an answer.
As is clear from all the previous answers, you cannot do the typecast. However, using AutoMapper, in a few lines of code you can have a new SkyfilterClient instantiated based on an existing NetworkClient.
In essence, you would put the following where you are currently doing your typecasting:
using AutoMapper;
...
// somewhere, your network client was declared
var existingNetworkClient = new NetworkClient();
...
// now we want to type-cast, but we can't, so we instantiate using AutoMapper
AutoMapper.Mapper.CreateMap<NetworkClient, SkyfilterClient>();
var skyfilterObject = AutoMapper.Mapper.Map<SkyfilterClient>(existingNetworkClient);
Here's a full-blown example:
public class Vehicle
{
public int NumWheels { get; set; }
public bool HasMotor { get; set; }
}
public class Car: Vehicle
{
public string Color { get; set; }
public string SteeringColumnStyle { get; set; }
}
public class CarMaker
{
// I am given vehicles that I want to turn into cars...
public List<Car> Convert(List<Vehicle> vehicles)
{
var cars = new List<Car>();
AutoMapper.Mapper.CreateMap<Vehicle, Car>(); // Declare that we want some automagic to happen
foreach (var vehicle in vehicles)
{
var car = AutoMapper.Mapper.Map<Car>(vehicle);
// At this point, the car-specific properties (Color and SteeringColumnStyle) are null, because there are no properties in the Vehicle object to map from.
// However, car's NumWheels and HasMotor properties which exist due to inheritance, are populated by AutoMapper.
cars.Add(car);
}
return cars;
}
}

If you HAVE to, and you don't mind a hack, you could let serialization do the work for you.
Given these classes:
public class ParentObj
{
public string Name { get; set; }
}
public class ChildObj : ParentObj
{
public string Value { get; set; }
}
You can create a child instance from a parent instance like so:
var parent = new ParentObj() { Name = "something" };
var serialized = JsonConvert.SerializeObject(parent);
var child = JsonConvert.DeserializeObject<ChildObj>(serialized);
This assumes your objects play nice with serialization, obv.
Be aware that this is probably going to be slower than an explicit converter.

In OOP, you can't cast an instance of a parent class into a child class. You can only cast a child instance into a parent that it inherits from.

I don't think you can downcast an object, however there is a simple way to "downcast" the object outside the box. It isn't type safe, but it works. First serialize the object into json, then deserialize it into the child class object. It works the same as if you were passing the object between apis. So, while there are some people who may say "this doesn't work or isn't good", I would argue that it is exactly the way our internet currently works, so... why not use that method? No mapping required as long as parameter names are the same, and they will be if it is a child class. Note: This will likely not copy any private fields; if you have a constructor with parameters, this probably needs to be tested as well to ensure there aren't side effects.
Here's my toolbox:
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);
}
Here's how to use it:
var sfcl = networkClient.ConvertToJson().ConvertToObject<SkyfilterClient>();

There's a few ways of doing this. However, here is one of the easiest ways to do this and it's reusable.
What is happening is that we're getting all the properties of the parent class and updating those same properties on the child class. Where baseObj would be the parent object and T would be the child class.
public static T ConvertToDerived<T>(object baseObj) where T : new()
{
var derivedObj = new T();
var members = baseObj.GetType().GetMembers();
foreach (var member in members)
{
object val = null;
if (member.MemberType == MemberTypes.Field)
{
val = ((FieldInfo)member).GetValue(baseObj);
((FieldInfo)member).SetValue(derivedObj, val);
}
else if (member.MemberType == MemberTypes.Property)
{
val = ((PropertyInfo)member).GetValue(baseObj);
if (val is IList && val.GetType().IsGenericType)
{
var listType = val.GetType().GetGenericArguments().Single();
var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(listType));
foreach (var item in (IList)val)
{
list.Add(item);
}
((PropertyInfo)member).SetValue(baseObj, list, null);
}
if (((PropertyInfo)member).CanWrite)
((PropertyInfo)member).SetValue(derivedObj, val);
}
}
return derivedObj;
}

You can't downcast. If the parent object is created, it cannot be cast to the child.
One suggested workaround would be to Create an interface which the parent implements. Have the child override functionality if needed or just expose the parents functionality. Change the cast to be an interface and do the operations.
Edit: May be could also check if the object is a SkyfilterClient using is keyword
if(networkClient is SkyfilterClient)
{
}

You can copy value of Parent Class to a Child class. For instance, you could use reflection if that is the case.

You can use the as operator to perform certain types of conversions between compatible reference types or nullable types.
SkyfilterClient c = client as SkyfilterClient;
if (c != null)
{
//do something with it
}
NetworkClient c = new SkyfilterClient() as NetworkClient; // c is not null
SkyfilterClient c2 = new NetworkClient() as SkyfilterClient; // c2 is null

I would recommend identifying the functionality you need from any subclasses, and make a generic method to cast into the right subclass.
I had this same problem, but really didn't feel like creating some mapping class or importing a library.
Let's say you need the 'Authenticate' method to take behavior from the right subclass. In your NetworkClient:
protected bool Authenticate(string username, string password) {
//...
}
protected bool DoAuthenticate<T>(NetworkClient nc, string username, string password) where T : NetworkClient {
//Do a cast into the sub class.
T subInst = (T) nc;
return nc.Authenticate(username, password);
}

You can't upcast you can only downcast Derived Class to Base Class
, but what you want to probably do is "create" not "cast" a new derived object from an existing base class object - just do it in the derived class's constructor
public class BaseClass
{
public int Property1 { get; set; }
public int Property2 { get; set; }
public int Property3 { get; set; }
}
public class DerivedClass : BaseClass
{
public DerivedClass(BaseClass myBaseClassObject)
{
this.Property1 = myBaseClassObject.Property1;
this.Property2 = myBaseClassObject.Property2;
this.Property3 = myBaseClassObject.Property3;
}
public int DerivedClassProperty3 { get; set; }
public int DerivedClassProperty4 { get; set; }
public int DerivedClassProperty5 { get; set; }
}
DerivedClass myNewDerivedObject = new DerivedClass(baseClassObject);

Use the cast operator, as such:
var skyfilterClient = (SkyfilterClient)networkClient;

Related

C# - CS0572 Error When Trying to Populate a Class

C# Newbie Here.
I have a class below:
namespace CompanyDevice.DeviceResponseClasses
{
public class DeviceStatusClass
{
public class Root
{
public static string RequestCommand { get; set; }
}
}
}
In another namespace I have:
namespace CompanyDevice
{
public class StatusController : ApiController
{
public DeviceStatusClass Get()
{
var returnStatus = new DeviceStatusClass();
returnStatus.Root.RequestCommand = "Hello"; //'Root' is causing a CS0572 error
return returnStatus;
}
}
}
I'm sure I'm making some rudimentary error here. Could you please help me find it? Thanks.
You access static properties from the type, not from the instance.
DeviceStatusClass.Root.RequestCommand = "Command";
Because the property RequestCommand is static, there will only ever be one. Perhaps this is what you want, but likely is not based on your usage.
You can remove the static keyword from RequestCommand, then you can access it through the instance, however you will need to add a field or property for the instance of Root inside of DeviceStatusClass.
public class DeviceStatusClass
{
public Root root = new Root();
public class Root
{
public string RequestCommand { get; set; }
}
}
And use like you did originally.
public class StatusController : ApiController
{
public DeviceStatusClass Get()
{
var returnStatus = new DeviceStatusClass();
returnStatus.root.RequestCommand = "Hello";
return returnStatus;
}
}
You maybe have a java background. In c# nested classes only change the names, they do not make the parent class contain an instance of a child class
namespace CompanyDevice.DeviceResponseClasses
{
public class DeviceStatusClass
{
public class Root
{
public static string RequestCommand { get; set; }
}
public Root DeviceRoot {get;set;} <<<=== add this
}
}
and then
returnStatus.DeviceRoot.RequestCommand = "Hello";

Using reflection to cast unknown object to generic class

I have a method which takes an object as a parameter. Within that method I walk through that objects properties with reflection. Some properties are of a generic class type. I like to read a property of that generic class property, but I cannot cast it to a generic class.
public abstract class BaseClass
{
public int Id { get; set; }
}
public abstract class GenericClass<T>: BaseClass
{
public string Description { get; set; }
}
public class DerivedClassA: GenericClass<DerivedClassA>
{
public string A { get; set; }
}
public class DerivedClassB: GenericClass<DerivedClassB>
{
public string B { get; set; }
}
public class ReflectingClass: BaseClass
{
public string Code { get; set; }
public DerivedClassA DerA { get; set; }
public DerivedClassB DerB { get; set; }
}
public static void Reflecting(object obj)
{
var t = GetType(obj)
foreach (var pi in t.GetProperties())
{
if (obj.GetType().BaseType.GetGenericTypeDefinition() == typeof(GenericClass<>)
{
var genClassObjProperty = ((GenericClass<T>)obj).Description; // Error, cannot do this at all !!!
}
}
}
What I want is for the code to walk to the properties and whatever the derived class actually is get the Description property of the GenericClass it is derived from.
I am using a generic class, because elsewhere in the code I call methods by their derived class and get the proper class type without resorting to all kinds of cast and passing types. I.e:
DerivedClassA.DoSomething()
instead of
BaseClass.DoSomething<DerivedClassA>()
or
BaseClass.DoSomething(type derivedClassType)
Take a look at this:
public static void Reflecting(object obj)
{
foreach (var pi in obj.GetType().GetProperties())
{
if (pi.PropertyType.BaseType.IsGenericType
&& pi.PropertyType.BaseType.GetGenericTypeDefinition()
== typeof(GenericClass<>))
{
var propValue = pi.GetValue(obj);
if (propValue != null)
{
var description = propValue.GetType()
.GetProperty("Description").GetValue(propValue);
Console.WriteLine(description);
}
}
}
Console.ReadKey();
}
I think this is what you need.

How can I query different tables dynamically with LINQ?

So I'm not sure if you can do this or not, but I would like to avoid using SQL strings if I can. What I would like to do with Linq/DbContexts is the following that can be done easily with SQL:
string sql = "UPDATE " + tableName + " SET Status=0 WHERE Id=" + formId.ToString();
I can easily put this into a loop where tableName and formId are given dynamically and execute no problem.
I have multiple DbContexts, so I don't know of any way to do something like:
var db = new *dynamicallyChosenContext*()
var query = from p in db.*dynamicallyChosenAlso*
where p.Id == formId
select p;
foreach (var result in query)
{
result.Status = 0;
}
db.SaveChanges()
Thanks for the help!
Here is a piece of working code that can update different tables at runtime from different contexts without using reflection.
namespace DemoContexts
{
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
public interface IThing
{
int Id { get; set; }
int Status { get; set; }
}
public class FirstPersonThing : IThing
{
[System.ComponentModel.DataAnnotations.Key]
public int Id { get; set; }
public int Status { get; set; }
public string Foo { get; set; }
}
public class SecondPersonThing : IThing
{
[System.ComponentModel.DataAnnotations.Key]
public int Id { get; set; }
public int Status { get; set; }
public string Bar { get; set; }
}
public class FirstContext : DbContext
{
public FirstContext() : base("FirstContext") { }
public DbSet<FirstPersonThing> MyThings { get; set; }
public DbSet<SecondPersonThing> YourThings { get; set; }
}
public class SecondContext : DbContext
{
public SecondContext() : base("SecondContext") { }
public DbSet<FirstPersonThing> MyThings { get; set; }
public DbSet<SecondPersonThing> YourThings { get; set; }
}
class Program
{
static void Main(string[] args)
{
int contextType = 1;
int thingType = 1;
DbContext db = RunTimeCreatedContext(contextType);
IQueryable<IThing> collection = RunTimeCreatedCollection(db, thingType);
UpdateRuntimeDeterminedThings(db, collection, 1);
Console.ReadLine();
}
public static void UpdateRuntimeDeterminedThings(DbContext db,
IQueryable<IThing> collection,
int formId)
{
var querySet = collection.Where(p => p.Id == formId).ToList();
foreach (var result in querySet)
{
result.Status = 0;
}
db.SaveChanges();
}
static DbContext RunTimeCreatedContext(int contextType)
{
if (contextType == 0)
{
return new FirstContext();
}
else
{
return new SecondContext();
}
}
static IQueryable<IThing> RunTimeCreatedCollection(DbContext db, int thingType)
{
if (thingType == 0)
{
return db.Set(typeof(FirstPersonThing)) as IQueryable<IThing>;
}
else
{
return db.Set<SecondPersonThing>();
}
}
}
}
The first thing to note is that all this is statically typed so to perform a generic query against different types of objects these objects must have common property signatures and this conceptually is expressed in the IThing interface.
A second thing to note is how the IQueryable is generated. It is generated by the DbContext.Set Method (Type) in the first instance (for the FirstPersonThings), it is generated by the DbContext.Set<TEntity> Method in the second instance. The first uses a type determined at runtime and requires a cast (but could be useful to use passing types at runtime), the second uses generics and the types are determined at compile time. There are obviously a number of other ways that this function could work.
Finally the method UpdateRuntimeDeterminedThings works because it uses properties and methods that are shared across the types (either with base types/inheritance or by the implementation of interfaces).
None of this is actually dynamic programming (which is possible using the dynamic type) and I have used the term runtime determined rather than dynamic to describe how this works.
There is a technique in functional programming, called Currying, where you could pass as much parameters as you want, so you are able to access them.
Here is an exemple: http://blogs.msdn.com/b/sriram/archive/2005/08/07/448722.aspx
P.S: You could use a currying function to iterate through yours DBContexts.
I think you have to use reflection if you want to use 'code' and not sql strings. That's just how C# works... This is how you could do it:
using System;
using System.Data.Entity;
using System.Linq;
public class TestContext : DbContext
{
public DbSet<Box> Boxes { get; set; }
public DbSet<Thing> Things { get; set; }
}
public abstract class Base
{
public int Id { get; set; }
}
public class Box : Base
{
public string Title { get; set; }
}
public class Thing : Base
{
public string Name { get; set; }
}
internal class Program
{
private static void Main(string[] args)
{
var db = new TestContext();
DoIt(GetPropValue(db, "Boxes") as IQueryable<Base>);
DoIt(GetPropValue(db, "Things") as IQueryable<Base>);
}
private static void DoIt(IQueryable<Base> b)
{
Console.WriteLine(
b.Single(t => t.Id == 1).Id);
}
private static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
}
Obviously you can then put the strings in a list etc, whatever you need.

Why would BinaryFormatter attempt to cast an object of type marked [Serializable] to IConvertible?

I realize it has been well-established elsewhere that serializing your NHibernate domain objects is generally a bad idea. My question here is in trying to understand how BinaryFormatter works, and why the scenario below yields the InvalidCastException.
The class structure roughly looks like this:
[Serializable]
public class Parent
{
public virtual Child child{get; set;}
}
[Serializable]
public class Child
{
public virtual ICollection<GrandChild> GrandChildren { get; set; }
}
[Serializable]
public class GrandChild
{
public virtual Pet pet{get; set;}
}
[Serializable]
public class Pet
{
public virtual IList<Toy> Toys { get; set; }
}
[Serializable]
public class Toy
{
public string ToyName { get; set; }
}
The serialization method looks like this:
public static byte[] Serialize(this object t)
{
using (var ms = new MemoryStream())
{
BinarySerializer.Serialize(ms, t);
return ms.ToArray();
}
}
Sometimes when calling Serialization e.g.
Parent p = new Parent() ....;
p.Serialize();
I will get
Unable to cast object of type 'NHibernate.Collection.Generic.PersistentGenericBag`1[Toy]' to type 'System.IConvertible'.
(all collections are mapped with bag semantics).
Even NHibernate.Collection.Generic.PersistentGenericBag<T> is marked [Serializable]
So given that everything here is marked as [Serializable] why would BinaryFormatter be attempting to cast PersistentGenericBag to an IConvertible in the first place?
Edit: In case it's relevant, this is under .NET 3.5 and NHibernate 3.1.0
By having the Pet class inherit from System.Runtime.Serialization.ISerializable, we now have complete control over how the Pet Class, and its members, in this case Toy, are serialized and de-serialized. Please see System.Runtime.Serialization.ISerializable, for more information about implementing System.Runtime.Serialization.ISerializable.
The sample below will serialize and then de-serialize an instance of the Parent class into a byte array and back again.
The public method, public GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context), is called when the Pet type is being serialized; first we add an Int32 value indicating the number of items in the Toys list. Then we add each Toy from the list.
The protected constructor, protected Pet(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context), is called when this type is being de-serialized. First we read the number of items that were stored in the Toys list, then use that to read each Toy instance from the serialized stream.
Please notice that for each Toy instance added to the serialized stream, we give it a different name; in this case we simply appended the value of the index to the word Toy; i.e. "Toy1", "Toy2",... This is because each item in the serialized stream needs a unique name. See: System.Runtime.Serialization.ISerializable.
And by controlling the serialization/de-serialization of the Toys list in Pet, we can eliminate the problem of not being able to serialize/de-serialize the list based on the type: NHibernate.Collection.Generic.PersistentGenericBag.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
static class Program
{
static void Main(string[] args)
{
Parent p = new Parent();
p.child = new Child();
p.child.GrandChildren = new List<GrandChild>();
p.child.GrandChildren.Add(new GrandChild { pet = new Pet() });
p.child.GrandChildren.First().pet.Toys = new List<Toy>();
p.child.GrandChildren.First().pet.Toys.Add(new Toy { ToyName = "Test" });
byte[] result = Serialize(p);
Parent backAgain = Deserialize(result);
}
public static System.Runtime.Serialization.Formatters.Binary.BinaryFormatter BinarySerializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
public static byte[] Serialize(Parent p)
{
using (var ms = new System.IO.MemoryStream())
{
BinarySerializer.Serialize(ms, p);
return ms.ToArray();
}
}
public static Parent Deserialize( byte[] data)
{
using (var ms = new System.IO.MemoryStream(data))
{
return (Parent)BinarySerializer.Deserialize(ms);
}
}
}
[Serializable]
public class Parent
{
public virtual Child child { get; set; }
}
[Serializable]
public class Child
{
public virtual ICollection<GrandChild> GrandChildren { get; set; }
}
[Serializable]
public class GrandChild
{
public virtual Pet pet { get; set; }
}
[Serializable]
public class Pet : System.Runtime.Serialization.ISerializable
{
public Pet() { }
// called when de-serializing (binary)
protected Pet(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
{
Toys = new List<Toy>();
int counter = info.GetInt32("ListCount");
for (int index = 0; index < counter; index++)
{
Toys.Add((Toy)info.GetValue(string.Format("Toy{0}",index.ToString()),typeof(Toy)));
}
}
// called when serializing (binary)
public void GetObjectData(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
{
info.AddValue("ListCount", Toys.Count);
for (int index = 0; index < Toys.Count; index++)
{
info.AddValue(string.Format("Toy{0}", index.ToString()), Toys[index], typeof(Toy));
}
}
public virtual IList<Toy> Toys { get; set; }
}
[Serializable]
public class Toy
{
public string ToyName { get; set; }
}

Using XmlSerializer to serialize derived classes

I'm using XMLSerializer to serialize an object that contains a generic list
List <ChildBase> Children {get;set}
The problem is that each element derives from ChildBase which in fact is an abstract class.
When I try to deserialize, I get an invalidOperationException
Is there a way I can use XMLSerializer with derived objects?
Thanks.
There are three ways of doing this; either you can use [XmlInclude] against the type, or you can use XmlElement/XmlArrayItem against the property. They are all shown below; uncomment the pair you prefer:
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
public class MyWrapper {
//2: [XmlElement("A", Type = typeof(ChildA))]
//2: [XmlElement("B", Type = typeof(ChildB))]
//3: [XmlArrayItem("A", Type = typeof(ChildA))]
//3: [XmlArrayItem("B", Type = typeof(ChildB))]
public List<ChildClass> Data { get; set; }
}
//1: [XmlInclude(typeof(ChildA))]
//1: [XmlInclude(typeof(ChildB))]
public abstract class ChildClass {
public string ChildProp { get; set; }
}
public class ChildA : ChildClass {
public string AProp { get; set; }
}
public class ChildB : ChildClass {
public string BProp { get; set; }
}
static class Program {
static void Main() {
var ser = new XmlSerializer(typeof(MyWrapper));
var obj = new MyWrapper {
Data = new List<ChildClass> {
new ChildA { ChildProp = "abc", AProp = "def"},
new ChildB { ChildProp = "ghi", BProp = "jkl"}}
};
ser.Serialize(Console.Out, obj);
}
}
You may use XmlIncludeAttribute for this. Or see this post on another way of doing this.
Another option is to set the types dynamically from derived class if defined in another namespace:
XmlAttributeOverride

Categories

Resources