How to deserialize object with custom serializable properties? - c#

I'm trying to serialize/deserialize collection of interfaces, which basically is unsupported. I found a question on SO where a proposition is stated to provide a serializable wrapper properties for those properties which depends on interfaces. So that's what I have:
public class Serialize {
public Serialize() {
this.SCollection = new SerializableInterfacesCollection<ObservableCollection<A>>(new ObservableCollection<A>());
}
[XmlIgnore()]
public ObservableCollection<A> Collection {
get {
return this.SCollection.Value;
}
set {
SCollection.Value = value;
}
}
public SerializableInterfacesCollection<ObservableCollection<A>> SCollection { get; set; }
}
public interface A {
string Str { get; set; }
int Int { get; set; }
// bad properties... very bad:
B B { get; set; }
ObservableCollection<B> Collection {get;set;}
}
public interface B {
string Label { get; set; }
string Value { get; set; }
}
public class AImpl: A {
public AImpl() {
SB = new SerializableInterface<B>();
SCollection = new SerializableInterfacesCollection<ObservableCollection<B>>(new ObservableCollection<B>());
}
[XmlAttribute()]
public string Type = typeof(AImpl).FullName;
public string Str {get;set;}
public int Int {get;set;}
[XmlIgnore()]
public B B {
get {
return SB.Value;
}
set {
SB.Value = value;
}
}
public SerializableInterface<B> SB;
[XmlIgnore()]
public ObservableCollection<B> Collection {
get {
return SCollection.Value;
}
set {
SCollection.Value = value;
}
}
public SerializableInterfacesCollection<ObservableCollection<B>> SCollection { get; set; }
}
public class BImpl01: B {
[XmlAttribute()]
public string Type = typeof(BImpl01).FullName;
public string Label {get;set;}
public string Value {get;set;}
}
public class BImpl02: B {
[XmlAttribute()]
public string Type = typeof(BImpl02).FullName;
public string Label {get;set;}
public string Value {get;set;}
}
Everything works fine if the A interface does not include "bad properties" (and of course they do not appear in the AImpl class). If it does than the collection's element does not deserialize and stops after deserializing first property of interface B.
Here are the wrappers:
public class SerializableInterface<T>: IXmlSerializable {
public SerializableInterface(T value) {
Value = value;
}
public SerializableInterface() { }
public T Value { get; set; }
public const string TypeAttr = "Type";
public const string NullAttrValue = "null";
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema() {
return null;
}
public virtual void ReadXml(System.Xml.XmlReader reader) {
if (!reader.HasAttributes)
throw new FormatException("expected a type attribute!");
string type = reader.GetAttribute(TypeAttr);
reader.Read(); // consume the value
if (type == NullAttrValue)
return;// leave T at default value
XmlSerializer serializer = new XmlSerializer(Type.GetType(type));
this.Value = (T)serializer.Deserialize(reader);
}
public virtual void WriteXml(System.Xml.XmlWriter writer) {
if (Value == null) {
writer.WriteAttributeString(TypeAttr, NullAttrValue);
return;
}
try {
var type = Value.GetType();
var ser = new XmlSerializer(type);
writer.WriteAttributeString(TypeAttr, type.FullName);
ser.Serialize(writer, Value);
}
catch (Exception e) {
// some logging
throw e;
}
}
#endregion
}
public class SerializableInterfacesCollection<T>: SerializableInterface<T> where T: IList, new() {
public SerializableInterfacesCollection() { }
public SerializableInterfacesCollection(T value)
: base(value) {}
#region IXmlSerializable Members
public override void ReadXml(System.Xml.XmlReader reader) {
try {
if (!reader.HasAttributes)
throw new FormatException("No " + TypeAttr + " in element");
string type = reader.GetAttribute(TypeAttr);
if (string.IsNullOrEmpty(type) || type == NullAttrValue || type != typeof(T).FullName)
return;
reader.Read();
Value = new T();
while (reader.NodeType != XmlNodeType.EndElement) {
string typename = reader.GetAttribute(TypeAttr);
if (string.IsNullOrEmpty(typename)) {
throw new FormatException("Collection element has to have " + TypeAttr + " attribute specifing its type");
}
Type t = Type.GetType(typename);
if (null == t.GetInterface(typeof(T).GetProperty("Item").PropertyType.FullName))
break;
XmlSerializer xs = new XmlSerializer(t);
var o = xs.Deserialize(reader);
Value.Add(o);
}
}
catch (Exception e) {
// some logging
throw e;
}
}
public override void WriteXml(System.Xml.XmlWriter writer) {
if (Value == null) {
writer.WriteAttributeString(TypeAttr, NullAttrValue);
return;
}
try {
writer.WriteAttributeString(TypeAttr, Value.GetType().FullName);
foreach (var el in Value) {
var ser = new XmlSerializer(el.GetType());
ser.Serialize(writer, el);
}
}
catch (Exception e) {
// some logging
throw e;
}
}
#endregion
}
and here is a method generating data for tests:
private Serialize makeA() {
Serialize result = new Serialize();
for (int i = 0; i < 10; ++i) {
A a = new AImpl() { Str = "str " + i, Int = i, B = makeB(i) };
for (int j = 0; j < 10; ++j) {
a.Collection.Add(makeB(j));
}
result.Collection.Add(a);
}
return result;
}
B makeB(int i) {
if (i % 2 == 0) {
return new BImpl01(){Label= "Blabel " + i, Value="value b"+i};
}
else {
return new BImpl02(){Label= "B2label " + i, Value="value b2"+i};
}
}

Related

Assigning redis values/redis hash entries to Type T returns null value

I am getting NULL properties on the below code, while returning the hashed value in cacheData
Line where I get Null values for all properties:
var val = RedisUtils.ToHashEntries(db.HashGet(hashkey + ":" + clsobjname, id));
cacheData = RedisUtils.ConvertFromRedis(e);
Please help me to assign the hashedValues(HashGet/HashGetAll values) to type T CacheData
Code:
public class class1
{
public class SampleModel
{
public SampleModel()
{
EmployeeDetails = new List<employees>();
CountryDetails = new List<country>();
StateDetails = new List<State>();
}
public List<employees> EmployeeDetails { get; set; }
public List<country> CountryDetails { get; set; }
public List<State> StateDetails { get; set; }
}
[Serializable]
public class employees
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
[Serializable]
public class country
{
public int Id { get; set; }
public string countryName { get; set; }
}
[Serializable]
public class State
{
public int Id { get; set; }
public int Name { get; set; }
}
private readonly IConnectionMultiplexer _connectionMultiplexer;
private readonly IConfiguration _Configuration;
private int cacheTypeAll;
private int cacheTypeMaster;
public class1(IConnectionMultiplexer connectionMultiplexer, IConfiguration configuration)
{
_connectionMultiplexer = connectionMultiplexer;
_Configuration = configuration;
cacheTypeAll = _Configuration.GetSection("AppSettings").GetValue<int>("CacheInstance");
cacheTypeMaster = _Configuration.GetSection("AppSettings").GetValue<int>("CacheInstanceMaster");
}
public async Task<T> GetRedisHash<T>(string hashkey, string id, SampleModel obj) where T : class
{
var db = _connectionMultiplexer.GetDatabase(cacheTypeAll);
T cacheData = null;
foreach (var a in obj.GetType().GetProperties())
{
var clsobjname = a.Name;
var HashGetAll = db.HashGetAll(hashkey + ":" + clsobjname);
var hashget = db.HashGet(hashkey + ":" + clsobjname, id);
if (HashGetAll.ToHashSet().Count > 0)
{
if (clsobjname != null)
{
if (id != "")
{
var e = RedisUtils.ToHashEntries(db.HashGet(hashkey + ":" + clsobjname, id));
cacheData = RedisUtils.ConvertFromRedis<T>(e);
}
else
{
var d = RedisUtils.ToHashEntries(db.HashGetAll(hashkey + ":" + clsobjname));
cacheData = RedisUtils.ConvertFromRedis<T>(d);
}
}
}
else
{
//cacheData = await computeData();
// string serializedData = JsonConvert.SerializeObject(cacheData);
string serializedData = "{'EmployeeDetails':[{'Id':1,'FirstName':'Anderson','LastName':'Felipe'},{'Id':2,'FirstName':'Anita','LastName':'Kay'},{'Id':3,'FirstName':'Karte','LastName':'Hare'}],'CountryDetails':[{'Id':1,'Name':'UK'}],'StateDetails':[{'Id':1,'Name':'UK'}]}";//I have set it static
dynamic parseJson = JsonConvert.DeserializeObject(serializedData);
foreach (var h in parseJson)
{
var c = ((Newtonsoft.Json.Linq.JProperty)((Newtonsoft.Json.Linq.JToken)h)).Value;
var objname = ((Newtonsoft.Json.Linq.JProperty)h).Name;
int i = 0;
foreach (var b in c)
{
var Id = c[i]["Id"];
db.HashSet(hashkey + ":" + objname, new HashEntry[] {
new HashEntry(Id.ToString(),JsonConvert.SerializeObject(c[i]))});
i++;
}
}
}
clsobjname = "";
}
return cacheData;
}
}
public static class RedisUtils
{
// Serialize in Redis format:
public static HashEntry[] ToHashEntries(this object obj)
{
PropertyInfo[] properties = obj.GetType().GetProperties();
return properties.Select(property => new HashEntry(property.Name, property.GetValue(obj).ToString())).ToArray();
}
//Deserialize from Redis format
public static T ConvertFromRedis<T>(this HashEntry[] hashEntries)
{
PropertyInfo[] properties = typeof(T).GetProperties();
var obj = Activator.CreateInstance(typeof(T));
foreach (var property in properties)
{
HashEntry entry = hashEntries.FirstOrDefault(g => g.Name.ToString().Equals(property.Name));
if (entry.Equals(new HashEntry())) continue;
property.SetValue(obj, Convert.ChangeType(entry.Value.ToString(), property.PropertyType));
}
return (T)obj;
}
}

c# using other class method

Thanks to NHMountainGoat for an answer!
Implementing Interface looks a good choice so we have only the 'needed' method instanciated.
It looks like this now:
EDIT
class Machine
{
//REM: MachineConnexion is a link to the main server where asking the data
internal linkToPLC LinkToPLC;
public IlinkToPLC ILinkPLC;
public interface IlinkToPLC//Interface to linkPLC
{
Int16 MachineNumIS { get; set; }
}
internal class linkToPLC : IlinkToPLC
{
private Int16 Act_MachineNum;
private List<string> genlnkPLCCanvas;
private List<string> genlnkPLCworkingwith;
static private List<string> ListSymbolNoExist;
private string[] ListToPLClnk = {
"GlobalFolder.PMachine[{0}].",
"GlobalFolder.PMachine[{0}].STATE.",
"GlobalFolder.Machine[{0}].",
"GlobalFolder.Machine[{0}].STATE.",
};
public linkToPLC()//ctor
{
genlnkPLCCanvas = new List<string>(ListToPLClnk);
genlnkPLCworkingwith = new List<string>(ListToPLClnk);
ListSymbolNoExist = new List<string>();
Act_MachineNum = MachineNumIS;
}
public Int16 MachineNumIS { get { return (Int16)ReadWriteMachine("data"); } set { ReadWriteMachine("data", value); } }
public string ValueExist(string ValueToreach, bool WorkingDATA = false)
{
if (!WorkingDATA)
{
for (int inc = 0; inc < genlnkPLCworkingwith.Count; inc++)
{
string StrValueToReach = genlnkPLCworkingwith[inc] + ValueToreach;
if (MachineConnexion.SymbolExists(StrValueToReach))
{
ListSymbolNoExist.Clear();
return StrValueToReach;
}
else ListSymbolNoExist.Add(genlnkPLCworkingwith[inc] + ValueToreach);
}
}
else if (WorkingDATA)
{
string StrValueToReach = genlnkPLCworkingwith[10] + ValueToreach;
if (MachineConnexion.SymbolExists(StrValueToReach))
{
ListSymbolNoExist.Clear();
return StrValueToReach;
}
else ListSymbolNoExist.Add(genlnkPLCworkingwith[10] + ValueToreach);
}
if (ListSymbolNoExist.Count != 0)
{
string ErrorList = "";
for (int inc = 0; inc < ListSymbolNoExist.Count; inc++)
{
ErrorList = string.Concat(ErrorList + "Num: " + inc.ToString() + " " + ListSymbolNoExist[inc].ToString() + "\n");
}
Console.WriteLine("Error" + ErrorList);
}
return null;
}
public object ReadWriteMachine(string VariableName, object DataToWrite = null, bool WorkingDATA = false)
{
string valueToFind = "";
if (ValueExist(VariableName) != "FALSE")
{
if (DataToWrite != null) { MachineConnexion.WriteSymbol(valueToFind, DataToWrite); }
return MachineConnexion.ReadSymbol(valueToFind);
}
return VariableName;
}
}
public Machine() //constructor
{
LinkToPLC = new linkToPLC();
}
}
And It doesn't work telling me that the reference object is not defined to an instance of the object..... in the line : Machine() LinkToPLC = new linkToPLC();//REM I found the bug, it was me ;o)) 24112016
//REM 24112016
What are the main differences between those two concept: static Instance and Interface?
Example:
class Program
{
static void Main(string[] args)
{
ITestInterface InterInstance = new TestInterface();
//test Interface
bool value1 = true;
value1 = InterInstance.invert(value1);
InterInstance.print(value1);
//test Instance static
TestStaticInstance staticInstance = new TestStaticInstance();
staticInstance.Instance.invert(value1);
staticInstance.Instance.print(value1);
Console.ReadKey();
}
}
class TestInterface : ITestInterface
{
public bool invert(bool value)
{
return !value;
}
public void print(bool value)
{
Console.WriteLine(value.ToString()+"\n");
}
private void methodX()
{ }
}
interface ITestInterface
{
bool invert(bool value);
void print(bool value);
}
public class TestStaticInstance
{
public TestStaticInstance Instance;
public TestStaticInstance()
{
Instance = this;
}
internal bool invert(bool value)
{
return !value;
}
internal void print(bool value)
{
Console.WriteLine(value.ToString());
}
}
Thanks
Can you structure your other classes to take an instance of the link class? See:
/// <summary>
/// just a stub to demonstrate the model
/// </summary>
internal class Machine
{
public string ReadData() { return "this is data"; }
public void WriteData(string data) { Console.WriteLine(data); }
}
internal interface IMachineDataAccessor
{
string Read();
void Write(string data);
}
class LinkClass : IMachineDataAccessor
{
protected Machine _machine;
public LinkClass(Machine machine)
{
_machine = machine;
}
public void DoMyWork()
{
// insert work somewhere in here.
string dataFromMachine = Read();
Write("outbound data");
}
public string Read()
{
return _machine.ReadData();
}
public void Write(string data)
{
_machine.WriteData(data);
}
}
class PersistentClass
{
IMachineDataAccessor _machineImpl;
public PersistentClass(IMachineDataAccessor machineAccessImplementation)
{
_machineImpl = machineAccessImplementation;
}
public void DoMyWork()
{
string dataFromMachine = _machineImpl.Read();
// insert work here. Or anywhere, actually..
_machineImpl.Write("outbound data");
}
}
class StateClass
{
IMachineDataAccessor _machineImpl;
public StateClass(IMachineDataAccessor machineAccessImplementation)
{
_machineImpl = machineAccessImplementation;
}
public void DoMyWork()
{
string dataFromMachine = _machineImpl.Read();
// insert work here. Or anywhere, actually..
_machineImpl.Write("outbound data");
}
}
static void Main(string[] args)
{
LinkClass link = new LinkClass(new Machine());
PersistentClass persistent = new PersistentClass(link as IMachineDataAccessor);
StateClass state = new StateClass(link as IMachineDataAccessor);
persistent.DoMyWork();
state.DoMyWork();
link.DoMyWork();
}

How to mock protected members with multiple interfaces

How to mock this class in nUnit Tests?
public class OpenDataQuery: PagedQuery, IOpenDataQuery
{
private static Dictionary<string, SortItem> m_sortModes;
protected override Dictionary<string, SortItem> SortModes
{
get
{
if (m_sortModes == null)
{
m_sortModes = new Dictionary<string, SortItem>();
AddSortMode(m_sortModes, new SortItem(ObjectExtensions.GetNameFromExpression<OpenDataCategoriesModel, string>(m => m.Name), "Наименование ↑", true) { IsDefault = true });
AddSortMode(m_sortModes, new SortItem(ObjectExtensions.GetNameFromExpression<OpenDataCategoriesModel, string>(m => m.Name), "Наименование ↓"));
}
return m_sortModes;
}
}
public IEnumerable<OpenDataCategoriesModel> OpenDataCategories { get; set; }
public string OpenDataTags { get; set; }
}
and
public abstract class PagedQuery : IPagedQuery
{
private const int DEFAULT_PAGE = 1;
private const int DEFAULT_COUNT = 5;
private int? m_page;
private int? m_count;
private int? m_total;
private string m_sort;
public int? Page
{
get
{
if (m_page == null || m_page <= 0)
{
return DEFAULT_PAGE;
}
return m_page;
}
set { m_page = value; }
}
public int? Count
{
get
{
if (m_count == null || m_count <= 0)
{
return DEFAULT_COUNT;
}
return m_count;
}
set { m_count = value; }
}
public int? Total
{
get
{
if (m_total == null || m_total <= 0)
{
return 0;
}
return m_total;
}
set { m_total = value; }
}
public string SearchQuery { get; set; }
protected virtual Dictionary<string, SortItem> SortModes
{
get { return null; }
}
public string Sort
{
get
{
var sortMode = GetSortMode(m_sort);
if (sortMode == null)
{
var defaultSort = (from i in SortModes where i.Value.IsDefault select i).FirstOrDefault();
if (!string.IsNullOrWhiteSpace(defaultSort.Key))
{
return defaultSort.Key;
}
return (from i in SortModes select i.Key).First();
}
return m_sort;
}
set
{
m_sort = value;
}
}
protected void AddSortMode(Dictionary<string, SortItem> sortModes, SortItem sortItem)
{
sortModes.Add(
String.Format(
"{0}{1}",
sortItem.FieldName.ToLower(),
sortItem.Asc ? "asc" : "desc"
),
sortItem
);
}
private SortItem GetSortMode(string sort)
{
if (SortModes == null || string.IsNullOrWhiteSpace(sort) ||
!SortModes.ContainsKey(sort.ToLower()))
{
return null;
}
return SortModes[sort.ToLower()];
}
public IOrderBy GetOrderBy()
{
var item = GetCurrentSortItem();
if (item == null)
{
return null;
}
if (item.Asc)
{
return new OrderBy(item.FieldName);
}
return new OrderByDesc(item.FieldName);
}
public SortItem GetCurrentSortItem()
{
return GetSortMode(Sort);
}
public Dictionary<string, SortItem> GetSortItems()
{
return SortModes;
}
}
and
public interface IOpenDataQuery : IPagedQuery
{
string OpenDataTags { get; set; }
}
I have some service method, that used openDataQuery class in parameters and in unit test i am trying mock this class, but this doesn't work:
public partial class OpenDataQueryRepository : Mock<OpenDataQuery>
{
public OpenDataQueryRepository(MockBehavior mockBehavior = MockBehavior.Strict)
: base(mockBehavior)
{
var opendataQuery = new Mock<IOpenDataQuery>();
var pagedQuery = opendataQuery.As<IPagedQuery>();
this.Setup(p=>p.GetOpenDataCategoriesMain(pagedQuery.Object,outttl)).Returns(OpenDataCategories);
}
}
I know that i should use Moq.Protected() for protected methods, but i don't know how use it correctly in this case. Please help me.
UPDATE:
I am testing this controller:
public class ODOpenDataController : ODBaseController
{
private readonly IOpenDataProvider m_openDataProvider;
public ODOpenDataController(IOpenDataProvider openDataProvider)
{
m_openDataProvider = openDataProvider;
}
public ActionResult Index(OpenDataQuery query)
{
int total;
query.OpenDataCategories = m_openDataProvider.GetOpenDataCategoriesMain(query, out total)
query.Total = total;
return View(query);
}
}
Test:
[Test]
public void Index_Test()
{
var opendataController = new ODOpenDataController(new OpenDataRepository().Object);
var result = opendataController.Index(new OpenDataQuery()) as ViewResult;
var model = result.Model as OpenDataQuery;
Assert.IsTrue(model.OpenDataCategories.Count() == 1);
}

what is the best way to dynamicly load classes and invoke them

This is what I came up with, but it feels bloated and well, untidy. And I don't like that I have created an instance of each class just to get the right one.
class FileHasher
{
private readonly List<IHasher> _list;
public FileHasher()
{
_list = new List<IHasher>();
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
if(typeof(IHasher).IsAssignableFrom(type) && type.IsClass)
_list.Add((IHasher) Activator.CreateInstance(type));
}
}
public HashReturn GetHashFromFile(string file, HashFileType hashType)
{
var hashReturn = new HashReturn();
IHasher iHasher = _list.Find(hasher => hasher.HashType == hashType);
hashReturn.Hash = iHasher.FileToHash(file);
return hashReturn;
}
public HashReturn GetHashFromString(string str, HashFileType hashType)
{
var hashReturn = new HashReturn();
IHasher iHasher = _list.Find(hasher => hasher.HashType == hashType);
hashReturn.Hash = iHasher.StringToHash(str);
return hashReturn;
}
}
internal class HashReturn
{
public Exception Error { get; set; }
public string Hash { get; set; }
public bool Success { get; set; }
}
enum HashFileType
{
CRC32,
MD5
}
internal interface IHasher
{
HashFileType HashType { get; }
string FileToHash(string file);
string StringToHash(string str);
}
class MD5Hasher : IHasher
{
public HashFileType HashType { get { return HashFileType.MD5; } }
public string FileToHash(string file)
{
return "";
}
public string StringToHash(string str)
{
return "";
}
}
class CRC32Hasher : IHasher
{
public HashFileType HashType { get { return HashFileType.CRC32; } }
public string FileToHash(string file)
{
return "";
}
public string StringToHash(string str)
{
return "";
}
}
MEF solves this nicely for you.
http://mef.codeplex.com/
It is included in .NET 4.

Serialize two nodes with the same name but different child nodes

I need to be able to define two nodes with the same name but completely different subnode structures. I didn't design this XML schema but for the time being I'm forced to use it as is. I realize it's a terrible abuse of everything that is XML but there you have it.
What I need it to look like:
<order>
<ItemType type="Clubs">
<Club num="1">
<ClubName>Some Name</ClubName>
<ClubChoice>Something Else</ClubChoice>
</Club>
</ItemType>
<ItemType type="Gift" val="MailGreeting">
<GiftName>MailGreeting</GiftName>
<GiftDescription></GiftDescription>
<GiftQuanity>1</GiftQuanity>
</ItemType
</order>
Of course it's far more complicated than but you get the gist.
I'm using XmlSerializer and would really like to avoid using XDocument but if that's what I need to do then so be it.
If your order contains properties and not a list you can tell the serializer to name the elements like this:
[XmlRoot("order")]
public class Order
{
private Whatever whateverInstance;
[XmlElement("ItemType")]
public Whatever WhateverInstance
{
get { return whateverInstance; }
set { whateverInstance = value; }
}
private Something somethingInstance;
[XmlElement("ItemType")]
public Something SomethingInstance
{
get { return somethingInstance; }
set { somethingInstance = value; }
}
}
If it's a list of things you could get to have a identical element name as well but you will get a redundant xsi:Type attribute:
[XmlRoot("order")]
public class Order
{
private ItemType[] itemTypes;
[XmlElement("ItemType")]
public ItemType[] ItemTypes
{
get { return itemTypes; }
set { itemTypes = value; }
}
}
[XmlInclude(typeof(Clubs))]
[XmlInclude(typeof(Gift))]
public abstract class ItemType
{
private string type = "None";
[XmlAttribute]
public string Type
{
get { return type; }
set { type = value; }
}
}
public class Clubs : ItemType
{
public Clubs()
{
Type = "Clubs";
}
private Club[] clubsArray;
[XmlElement("Club")]
public Club[] ClubsArray
{
get { return clubsArray; }
set { clubsArray = value; }
}
}
public class Club
{
private int num = 0;
[XmlAttribute("num")]
public int Num
{
get { return num; }
set { num = value; }
}
private string clubName = "";
public string ClubName
{
get { return clubName; }
set { clubName = value; }
}
private string clubChoice = "";
public string ClubChoice
{
get { return clubChoice; }
set { clubChoice = value; }
}
}
public class Gift : ItemType
{
public Gift()
{
Type = "Gift";
}
private string val = "";
[XmlAttribute("val")]
public string Val
{
get { return val; }
set { val = value; }
}
private string giftName = "";
public string GiftName
{
get { return giftName; }
set { giftName = value; }
}
private string giftDescription = "";
public string GiftDescription
{
get { return giftDescription; }
set { giftDescription = value; }
}
private int giftQuanity = 0;
public int GiftQuanity
{
get { return giftQuanity; }
set { giftQuanity = value; }
}
}
Test:
List<ItemType> list = new List<ItemType>();
list.Add(new Clubs() { ClubsArray = new Club[] { new Club() { Num = 0, ClubName = "Some Name", ClubChoice = "Something Else" } } });
list.Add(new Gift() { Val = "MailGreeting", GiftName = "MailGreeting", GiftDescription = "GiftDescription", GiftQuanity = 1});
Order order = new Order();
rder.ItemTypes = list.ToArray();
XmlSerializer serializer = new XmlSerializer(typeof(Order));
StreamWriter sw = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\Stuff.xml");
serializer.Serialize(sw, order);
sw.Close();
Output:
<order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ItemType xsi:type="Clubs" Type="Clubs">
<Club num="0">
<ClubName>Some Name</ClubName>
<ClubChoice>Something Else</ClubChoice>
</Club>
</ItemType>
<ItemType xsi:type="Gift" Type="Gift" val="MailGreeting">
<GiftName>MailGreeting</GiftName>
<GiftDescription>GiftDescription</GiftDescription>
<GiftQuanity>1</GiftQuanity>
</ItemType>
</order>

Categories

Resources