Deserialize class properties to derived class instead of base abstract class
The structure here is a bit convoluted so please bear with me. I hope that there's a way to do what a want to do, but if it's not possible then feel free to tell me!
Unfortunately I've not been involved in the design process of the XML file spec from the beginning, the goalposts have been moved a dozen times and the spec can't be amended for the sake of making it easier for me to do as any spec amendments are extortionately priced (yes, even renaming XML elements!)
Anyway I digress.
There are two different types of purchase order that have a slightly different file structure and slightly different processing logic and I am trying to handle them both with the same code instead of having two different projects for what is nearly identical.
Both types of purchase order derive from a set of abstract classes that determine basic business logic that both PO types share (quantity, cost, PO number, etc.).
Base classes
abstract class PO
[XmlIgnore]
abstract POType PurchaseOrderType get;
[XmlIgnore]
abstract PO_Head Header get;set;
[XmlIgnore]
abstract List<PO_Line> LineItems get;set;
abstract class PO_Head
[XmlIgnore]
abstract string PONumber get;set;
abstract class PO_Line
[XmlIgnore]
abstract string ItemCode get;set;
[XmlIgnore]
abstract decimal UnitCost get;set;
[XmlIgnore]
abstract int OrderQty get;set;
Derived classes
class POR : PO
// POR implementations
class POR_Head : PO_Line
// POR implementations
class POR_Line : PO_Line
// POR implementations
class CPO : PO
// CPO implementations
class CPO_Head : PO_Line
// CPO implementations
class CPO_Line : PO_Line
// CPO implementations
The base abstract class is then used in the code to process each purchase order and import them into our accounting system.
for (int i = pending.Transactions.Count -1; i > -1; i--)
PO pendingOrder = (PO)pending.Transactions[i];
// Import PO type
The problem is that when I attempt to deserialize into each derived class as appropriate, it attempts to deserialize the Header
and LineItems
into the derived types PO_Head
and PO_Line
. Is there any way I can explicitly tell the XmlSerializer
to treat Header
and LineItems
as the derived class versions - CPO_Head and CPO_Line or POR_Head and POR_Line - depending on the class that is being serialized - CPO or POR respectively. Something akin to the below.
class CPO : PO
[XmlIgnore]
override POType PurchaseOrderType => POType.CPO;
[XmlElement("CPO_Head")]
[XmlDeserializerType(typeof(CPO_Head))]
override PO_Head Header get;set;
[XmlArray("CPO_Lines")]
[XmlArrayItem("CPO_Line")]
[XmlDeserializerType(typeof(CPO_Line))]
override List<PO_Line> LineItems get;set;
Kind of dug myself a hole with this one (first time using deserialization) so I'm hoping there's an easy way out that would save me having to rewrite a ton of the work I've done!
TIA
EDIT - code used to deserialize/serialize as requested
public static void SerializeToXmlFile(object obj, FileInfo dstFile)
XmlSerializer xmlSerializer = new XmlSerializer(obj.GetType());
using (FileStream fs = dstFile.Open(FileMode.Create, FileAccess.Write))
xmlSerializer.Serialize(fs, obj);
public static object DeserializeFromXmlFile(FileInfo srcFile, Type type)
XmlSerializer xmlSerializer = new XmlSerializer(type);
using (FileStream fs = srcFile.Open(FileMode.Open, FileAccess.Read))
return xmlSerializer.Deserialize(fs);
public static void Main(string args)
// Deserialize from XML file
FileInfo srcFile = new FileInfo("pathtofile");
Type t;
if (srcFile.Name.Substring(0,3) == "CPO")
t = typeof(CPO);
else if (srcFile.Name.Substring(0,3) == "POR")
t = typeof(POR);
PO po = DeserializeFromXmlFile(file, t);
// Process the file
// ...
// Serialize back to file
FileInfo dstFile = new FileInfo("newpathtofile");
SerializeToXmlFile(po, dstFile);
EDIT - fixed
As per the marked correct answer I was able to resolve this by specifying the Type
in the XmlElement
and XmlArrayItem
attributes.
class POR
[XmlElement(typeof(POR_Head), ElementName="PO_Head")]
override PO_Head Header get;set; = new POR_Head();
[XmlArray("PO_Lines")]
[XmlArrayItem(typeof(POR_Line), ElementName="PO_Line")]
override List<PO_Line> LineItems get;set; = new List<LineItems>();
class CPO
[XmlElement(typeof(CPO_Head), ElementName="PO_Head")]
override PO_Head Header get;set; = new CPO_Head();
[XmlArray("PO_Lines")]
[XmlArrayItem(typeof(CPO_Line), ElementName="PO_Line")]
override List<PO_Line> LineItems get;set; = new List<LineItems>();
c# xml-deserialization
add a comment |
The structure here is a bit convoluted so please bear with me. I hope that there's a way to do what a want to do, but if it's not possible then feel free to tell me!
Unfortunately I've not been involved in the design process of the XML file spec from the beginning, the goalposts have been moved a dozen times and the spec can't be amended for the sake of making it easier for me to do as any spec amendments are extortionately priced (yes, even renaming XML elements!)
Anyway I digress.
There are two different types of purchase order that have a slightly different file structure and slightly different processing logic and I am trying to handle them both with the same code instead of having two different projects for what is nearly identical.
Both types of purchase order derive from a set of abstract classes that determine basic business logic that both PO types share (quantity, cost, PO number, etc.).
Base classes
abstract class PO
[XmlIgnore]
abstract POType PurchaseOrderType get;
[XmlIgnore]
abstract PO_Head Header get;set;
[XmlIgnore]
abstract List<PO_Line> LineItems get;set;
abstract class PO_Head
[XmlIgnore]
abstract string PONumber get;set;
abstract class PO_Line
[XmlIgnore]
abstract string ItemCode get;set;
[XmlIgnore]
abstract decimal UnitCost get;set;
[XmlIgnore]
abstract int OrderQty get;set;
Derived classes
class POR : PO
// POR implementations
class POR_Head : PO_Line
// POR implementations
class POR_Line : PO_Line
// POR implementations
class CPO : PO
// CPO implementations
class CPO_Head : PO_Line
// CPO implementations
class CPO_Line : PO_Line
// CPO implementations
The base abstract class is then used in the code to process each purchase order and import them into our accounting system.
for (int i = pending.Transactions.Count -1; i > -1; i--)
PO pendingOrder = (PO)pending.Transactions[i];
// Import PO type
The problem is that when I attempt to deserialize into each derived class as appropriate, it attempts to deserialize the Header
and LineItems
into the derived types PO_Head
and PO_Line
. Is there any way I can explicitly tell the XmlSerializer
to treat Header
and LineItems
as the derived class versions - CPO_Head and CPO_Line or POR_Head and POR_Line - depending on the class that is being serialized - CPO or POR respectively. Something akin to the below.
class CPO : PO
[XmlIgnore]
override POType PurchaseOrderType => POType.CPO;
[XmlElement("CPO_Head")]
[XmlDeserializerType(typeof(CPO_Head))]
override PO_Head Header get;set;
[XmlArray("CPO_Lines")]
[XmlArrayItem("CPO_Line")]
[XmlDeserializerType(typeof(CPO_Line))]
override List<PO_Line> LineItems get;set;
Kind of dug myself a hole with this one (first time using deserialization) so I'm hoping there's an easy way out that would save me having to rewrite a ton of the work I've done!
TIA
EDIT - code used to deserialize/serialize as requested
public static void SerializeToXmlFile(object obj, FileInfo dstFile)
XmlSerializer xmlSerializer = new XmlSerializer(obj.GetType());
using (FileStream fs = dstFile.Open(FileMode.Create, FileAccess.Write))
xmlSerializer.Serialize(fs, obj);
public static object DeserializeFromXmlFile(FileInfo srcFile, Type type)
XmlSerializer xmlSerializer = new XmlSerializer(type);
using (FileStream fs = srcFile.Open(FileMode.Open, FileAccess.Read))
return xmlSerializer.Deserialize(fs);
public static void Main(string args)
// Deserialize from XML file
FileInfo srcFile = new FileInfo("pathtofile");
Type t;
if (srcFile.Name.Substring(0,3) == "CPO")
t = typeof(CPO);
else if (srcFile.Name.Substring(0,3) == "POR")
t = typeof(POR);
PO po = DeserializeFromXmlFile(file, t);
// Process the file
// ...
// Serialize back to file
FileInfo dstFile = new FileInfo("newpathtofile");
SerializeToXmlFile(po, dstFile);
EDIT - fixed
As per the marked correct answer I was able to resolve this by specifying the Type
in the XmlElement
and XmlArrayItem
attributes.
class POR
[XmlElement(typeof(POR_Head), ElementName="PO_Head")]
override PO_Head Header get;set; = new POR_Head();
[XmlArray("PO_Lines")]
[XmlArrayItem(typeof(POR_Line), ElementName="PO_Line")]
override List<PO_Line> LineItems get;set; = new List<LineItems>();
class CPO
[XmlElement(typeof(CPO_Head), ElementName="PO_Head")]
override PO_Head Header get;set; = new CPO_Head();
[XmlArray("PO_Lines")]
[XmlArrayItem(typeof(CPO_Line), ElementName="PO_Line")]
override List<PO_Line> LineItems get;set; = new List<LineItems>();
c# xml-deserialization
When working with weakly typed stuff (inlcuding unstable structured XML), there is the ExpandoObject class. Deserialize the XML into a ExpandoObject. Then later decide wich proper .NET class you translate it too, based on the values in the EO. That allows you to seperate the deserialization of the data and hte picking of the proper (sub) class.
– Christopher
Nov 12 '18 at 17:10
Can you edit your post to include the code that you are using to serialize and deserialize the objects?
– John Wu
Nov 12 '18 at 17:35
@JohnWu I have added that code as requested.
– ryansin
Nov 13 '18 at 8:23
@Christopher can you add an example ofExpandoObject
please?
– ryansin
Nov 13 '18 at 8:37
add a comment |
The structure here is a bit convoluted so please bear with me. I hope that there's a way to do what a want to do, but if it's not possible then feel free to tell me!
Unfortunately I've not been involved in the design process of the XML file spec from the beginning, the goalposts have been moved a dozen times and the spec can't be amended for the sake of making it easier for me to do as any spec amendments are extortionately priced (yes, even renaming XML elements!)
Anyway I digress.
There are two different types of purchase order that have a slightly different file structure and slightly different processing logic and I am trying to handle them both with the same code instead of having two different projects for what is nearly identical.
Both types of purchase order derive from a set of abstract classes that determine basic business logic that both PO types share (quantity, cost, PO number, etc.).
Base classes
abstract class PO
[XmlIgnore]
abstract POType PurchaseOrderType get;
[XmlIgnore]
abstract PO_Head Header get;set;
[XmlIgnore]
abstract List<PO_Line> LineItems get;set;
abstract class PO_Head
[XmlIgnore]
abstract string PONumber get;set;
abstract class PO_Line
[XmlIgnore]
abstract string ItemCode get;set;
[XmlIgnore]
abstract decimal UnitCost get;set;
[XmlIgnore]
abstract int OrderQty get;set;
Derived classes
class POR : PO
// POR implementations
class POR_Head : PO_Line
// POR implementations
class POR_Line : PO_Line
// POR implementations
class CPO : PO
// CPO implementations
class CPO_Head : PO_Line
// CPO implementations
class CPO_Line : PO_Line
// CPO implementations
The base abstract class is then used in the code to process each purchase order and import them into our accounting system.
for (int i = pending.Transactions.Count -1; i > -1; i--)
PO pendingOrder = (PO)pending.Transactions[i];
// Import PO type
The problem is that when I attempt to deserialize into each derived class as appropriate, it attempts to deserialize the Header
and LineItems
into the derived types PO_Head
and PO_Line
. Is there any way I can explicitly tell the XmlSerializer
to treat Header
and LineItems
as the derived class versions - CPO_Head and CPO_Line or POR_Head and POR_Line - depending on the class that is being serialized - CPO or POR respectively. Something akin to the below.
class CPO : PO
[XmlIgnore]
override POType PurchaseOrderType => POType.CPO;
[XmlElement("CPO_Head")]
[XmlDeserializerType(typeof(CPO_Head))]
override PO_Head Header get;set;
[XmlArray("CPO_Lines")]
[XmlArrayItem("CPO_Line")]
[XmlDeserializerType(typeof(CPO_Line))]
override List<PO_Line> LineItems get;set;
Kind of dug myself a hole with this one (first time using deserialization) so I'm hoping there's an easy way out that would save me having to rewrite a ton of the work I've done!
TIA
EDIT - code used to deserialize/serialize as requested
public static void SerializeToXmlFile(object obj, FileInfo dstFile)
XmlSerializer xmlSerializer = new XmlSerializer(obj.GetType());
using (FileStream fs = dstFile.Open(FileMode.Create, FileAccess.Write))
xmlSerializer.Serialize(fs, obj);
public static object DeserializeFromXmlFile(FileInfo srcFile, Type type)
XmlSerializer xmlSerializer = new XmlSerializer(type);
using (FileStream fs = srcFile.Open(FileMode.Open, FileAccess.Read))
return xmlSerializer.Deserialize(fs);
public static void Main(string args)
// Deserialize from XML file
FileInfo srcFile = new FileInfo("pathtofile");
Type t;
if (srcFile.Name.Substring(0,3) == "CPO")
t = typeof(CPO);
else if (srcFile.Name.Substring(0,3) == "POR")
t = typeof(POR);
PO po = DeserializeFromXmlFile(file, t);
// Process the file
// ...
// Serialize back to file
FileInfo dstFile = new FileInfo("newpathtofile");
SerializeToXmlFile(po, dstFile);
EDIT - fixed
As per the marked correct answer I was able to resolve this by specifying the Type
in the XmlElement
and XmlArrayItem
attributes.
class POR
[XmlElement(typeof(POR_Head), ElementName="PO_Head")]
override PO_Head Header get;set; = new POR_Head();
[XmlArray("PO_Lines")]
[XmlArrayItem(typeof(POR_Line), ElementName="PO_Line")]
override List<PO_Line> LineItems get;set; = new List<LineItems>();
class CPO
[XmlElement(typeof(CPO_Head), ElementName="PO_Head")]
override PO_Head Header get;set; = new CPO_Head();
[XmlArray("PO_Lines")]
[XmlArrayItem(typeof(CPO_Line), ElementName="PO_Line")]
override List<PO_Line> LineItems get;set; = new List<LineItems>();
c# xml-deserialization
The structure here is a bit convoluted so please bear with me. I hope that there's a way to do what a want to do, but if it's not possible then feel free to tell me!
Unfortunately I've not been involved in the design process of the XML file spec from the beginning, the goalposts have been moved a dozen times and the spec can't be amended for the sake of making it easier for me to do as any spec amendments are extortionately priced (yes, even renaming XML elements!)
Anyway I digress.
There are two different types of purchase order that have a slightly different file structure and slightly different processing logic and I am trying to handle them both with the same code instead of having two different projects for what is nearly identical.
Both types of purchase order derive from a set of abstract classes that determine basic business logic that both PO types share (quantity, cost, PO number, etc.).
Base classes
abstract class PO
[XmlIgnore]
abstract POType PurchaseOrderType get;
[XmlIgnore]
abstract PO_Head Header get;set;
[XmlIgnore]
abstract List<PO_Line> LineItems get;set;
abstract class PO_Head
[XmlIgnore]
abstract string PONumber get;set;
abstract class PO_Line
[XmlIgnore]
abstract string ItemCode get;set;
[XmlIgnore]
abstract decimal UnitCost get;set;
[XmlIgnore]
abstract int OrderQty get;set;
Derived classes
class POR : PO
// POR implementations
class POR_Head : PO_Line
// POR implementations
class POR_Line : PO_Line
// POR implementations
class CPO : PO
// CPO implementations
class CPO_Head : PO_Line
// CPO implementations
class CPO_Line : PO_Line
// CPO implementations
The base abstract class is then used in the code to process each purchase order and import them into our accounting system.
for (int i = pending.Transactions.Count -1; i > -1; i--)
PO pendingOrder = (PO)pending.Transactions[i];
// Import PO type
The problem is that when I attempt to deserialize into each derived class as appropriate, it attempts to deserialize the Header
and LineItems
into the derived types PO_Head
and PO_Line
. Is there any way I can explicitly tell the XmlSerializer
to treat Header
and LineItems
as the derived class versions - CPO_Head and CPO_Line or POR_Head and POR_Line - depending on the class that is being serialized - CPO or POR respectively. Something akin to the below.
class CPO : PO
[XmlIgnore]
override POType PurchaseOrderType => POType.CPO;
[XmlElement("CPO_Head")]
[XmlDeserializerType(typeof(CPO_Head))]
override PO_Head Header get;set;
[XmlArray("CPO_Lines")]
[XmlArrayItem("CPO_Line")]
[XmlDeserializerType(typeof(CPO_Line))]
override List<PO_Line> LineItems get;set;
Kind of dug myself a hole with this one (first time using deserialization) so I'm hoping there's an easy way out that would save me having to rewrite a ton of the work I've done!
TIA
EDIT - code used to deserialize/serialize as requested
public static void SerializeToXmlFile(object obj, FileInfo dstFile)
XmlSerializer xmlSerializer = new XmlSerializer(obj.GetType());
using (FileStream fs = dstFile.Open(FileMode.Create, FileAccess.Write))
xmlSerializer.Serialize(fs, obj);
public static object DeserializeFromXmlFile(FileInfo srcFile, Type type)
XmlSerializer xmlSerializer = new XmlSerializer(type);
using (FileStream fs = srcFile.Open(FileMode.Open, FileAccess.Read))
return xmlSerializer.Deserialize(fs);
public static void Main(string args)
// Deserialize from XML file
FileInfo srcFile = new FileInfo("pathtofile");
Type t;
if (srcFile.Name.Substring(0,3) == "CPO")
t = typeof(CPO);
else if (srcFile.Name.Substring(0,3) == "POR")
t = typeof(POR);
PO po = DeserializeFromXmlFile(file, t);
// Process the file
// ...
// Serialize back to file
FileInfo dstFile = new FileInfo("newpathtofile");
SerializeToXmlFile(po, dstFile);
EDIT - fixed
As per the marked correct answer I was able to resolve this by specifying the Type
in the XmlElement
and XmlArrayItem
attributes.
class POR
[XmlElement(typeof(POR_Head), ElementName="PO_Head")]
override PO_Head Header get;set; = new POR_Head();
[XmlArray("PO_Lines")]
[XmlArrayItem(typeof(POR_Line), ElementName="PO_Line")]
override List<PO_Line> LineItems get;set; = new List<LineItems>();
class CPO
[XmlElement(typeof(CPO_Head), ElementName="PO_Head")]
override PO_Head Header get;set; = new CPO_Head();
[XmlArray("PO_Lines")]
[XmlArrayItem(typeof(CPO_Line), ElementName="PO_Line")]
override List<PO_Line> LineItems get;set; = new List<LineItems>();
c# xml-deserialization
c# xml-deserialization
edited Nov 13 '18 at 9:14
ryansin
asked Nov 12 '18 at 17:05
ryansinryansin
724725
724725
When working with weakly typed stuff (inlcuding unstable structured XML), there is the ExpandoObject class. Deserialize the XML into a ExpandoObject. Then later decide wich proper .NET class you translate it too, based on the values in the EO. That allows you to seperate the deserialization of the data and hte picking of the proper (sub) class.
– Christopher
Nov 12 '18 at 17:10
Can you edit your post to include the code that you are using to serialize and deserialize the objects?
– John Wu
Nov 12 '18 at 17:35
@JohnWu I have added that code as requested.
– ryansin
Nov 13 '18 at 8:23
@Christopher can you add an example ofExpandoObject
please?
– ryansin
Nov 13 '18 at 8:37
add a comment |
When working with weakly typed stuff (inlcuding unstable structured XML), there is the ExpandoObject class. Deserialize the XML into a ExpandoObject. Then later decide wich proper .NET class you translate it too, based on the values in the EO. That allows you to seperate the deserialization of the data and hte picking of the proper (sub) class.
– Christopher
Nov 12 '18 at 17:10
Can you edit your post to include the code that you are using to serialize and deserialize the objects?
– John Wu
Nov 12 '18 at 17:35
@JohnWu I have added that code as requested.
– ryansin
Nov 13 '18 at 8:23
@Christopher can you add an example ofExpandoObject
please?
– ryansin
Nov 13 '18 at 8:37
When working with weakly typed stuff (inlcuding unstable structured XML), there is the ExpandoObject class. Deserialize the XML into a ExpandoObject. Then later decide wich proper .NET class you translate it too, based on the values in the EO. That allows you to seperate the deserialization of the data and hte picking of the proper (sub) class.
– Christopher
Nov 12 '18 at 17:10
When working with weakly typed stuff (inlcuding unstable structured XML), there is the ExpandoObject class. Deserialize the XML into a ExpandoObject. Then later decide wich proper .NET class you translate it too, based on the values in the EO. That allows you to seperate the deserialization of the data and hte picking of the proper (sub) class.
– Christopher
Nov 12 '18 at 17:10
Can you edit your post to include the code that you are using to serialize and deserialize the objects?
– John Wu
Nov 12 '18 at 17:35
Can you edit your post to include the code that you are using to serialize and deserialize the objects?
– John Wu
Nov 12 '18 at 17:35
@JohnWu I have added that code as requested.
– ryansin
Nov 13 '18 at 8:23
@JohnWu I have added that code as requested.
– ryansin
Nov 13 '18 at 8:23
@Christopher can you add an example of
ExpandoObject
please?– ryansin
Nov 13 '18 at 8:37
@Christopher can you add an example of
ExpandoObject
please?– ryansin
Nov 13 '18 at 8:37
add a comment |
1 Answer
1
active
oldest
votes
I think you are looking for the XmlArrayItemAttribute. According to the docs:
You can apply the XmlArrayItemAttribute to any public read/write member that returns an array, or provides access to one. For example, a field that returns an array of objects, a collection, an ArrayList, or any class that implements the IEnumerable interface.
The XmlArrayItemAttribute supports polymorphism--in other words, it allows the XmlSerializer to add derived objects to an array.
If I understand the example correctly, the attribute should be written with a list of the possible derived types that are allowed in the serialized enumerable, e.g.
[XmlArrayItem (typeof(PO_Line), ElementName = "PO_Line"),
XmlArrayItem (typeof(CPO_Line),ElementName = "CPO_Line")]
Since you are only passing a string, the attribute interprets that as the ElementName, not the type. The type must be passed using typeof(ClassName)
.
Specifying the type in theXmlArrayItemAttribute
andXmlElementAttribute
is what fixed my issue, I will update my answer to show exactly what steps I took. Thanks so much!
– ryansin
Nov 13 '18 at 9:10
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53266907%2fdeserialize-class-properties-to-derived-class-instead-of-base-abstract-class%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I think you are looking for the XmlArrayItemAttribute. According to the docs:
You can apply the XmlArrayItemAttribute to any public read/write member that returns an array, or provides access to one. For example, a field that returns an array of objects, a collection, an ArrayList, or any class that implements the IEnumerable interface.
The XmlArrayItemAttribute supports polymorphism--in other words, it allows the XmlSerializer to add derived objects to an array.
If I understand the example correctly, the attribute should be written with a list of the possible derived types that are allowed in the serialized enumerable, e.g.
[XmlArrayItem (typeof(PO_Line), ElementName = "PO_Line"),
XmlArrayItem (typeof(CPO_Line),ElementName = "CPO_Line")]
Since you are only passing a string, the attribute interprets that as the ElementName, not the type. The type must be passed using typeof(ClassName)
.
Specifying the type in theXmlArrayItemAttribute
andXmlElementAttribute
is what fixed my issue, I will update my answer to show exactly what steps I took. Thanks so much!
– ryansin
Nov 13 '18 at 9:10
add a comment |
I think you are looking for the XmlArrayItemAttribute. According to the docs:
You can apply the XmlArrayItemAttribute to any public read/write member that returns an array, or provides access to one. For example, a field that returns an array of objects, a collection, an ArrayList, or any class that implements the IEnumerable interface.
The XmlArrayItemAttribute supports polymorphism--in other words, it allows the XmlSerializer to add derived objects to an array.
If I understand the example correctly, the attribute should be written with a list of the possible derived types that are allowed in the serialized enumerable, e.g.
[XmlArrayItem (typeof(PO_Line), ElementName = "PO_Line"),
XmlArrayItem (typeof(CPO_Line),ElementName = "CPO_Line")]
Since you are only passing a string, the attribute interprets that as the ElementName, not the type. The type must be passed using typeof(ClassName)
.
Specifying the type in theXmlArrayItemAttribute
andXmlElementAttribute
is what fixed my issue, I will update my answer to show exactly what steps I took. Thanks so much!
– ryansin
Nov 13 '18 at 9:10
add a comment |
I think you are looking for the XmlArrayItemAttribute. According to the docs:
You can apply the XmlArrayItemAttribute to any public read/write member that returns an array, or provides access to one. For example, a field that returns an array of objects, a collection, an ArrayList, or any class that implements the IEnumerable interface.
The XmlArrayItemAttribute supports polymorphism--in other words, it allows the XmlSerializer to add derived objects to an array.
If I understand the example correctly, the attribute should be written with a list of the possible derived types that are allowed in the serialized enumerable, e.g.
[XmlArrayItem (typeof(PO_Line), ElementName = "PO_Line"),
XmlArrayItem (typeof(CPO_Line),ElementName = "CPO_Line")]
Since you are only passing a string, the attribute interprets that as the ElementName, not the type. The type must be passed using typeof(ClassName)
.
I think you are looking for the XmlArrayItemAttribute. According to the docs:
You can apply the XmlArrayItemAttribute to any public read/write member that returns an array, or provides access to one. For example, a field that returns an array of objects, a collection, an ArrayList, or any class that implements the IEnumerable interface.
The XmlArrayItemAttribute supports polymorphism--in other words, it allows the XmlSerializer to add derived objects to an array.
If I understand the example correctly, the attribute should be written with a list of the possible derived types that are allowed in the serialized enumerable, e.g.
[XmlArrayItem (typeof(PO_Line), ElementName = "PO_Line"),
XmlArrayItem (typeof(CPO_Line),ElementName = "CPO_Line")]
Since you are only passing a string, the attribute interprets that as the ElementName, not the type. The type must be passed using typeof(ClassName)
.
answered Nov 13 '18 at 8:50
John WuJohn Wu
29.9k42752
29.9k42752
Specifying the type in theXmlArrayItemAttribute
andXmlElementAttribute
is what fixed my issue, I will update my answer to show exactly what steps I took. Thanks so much!
– ryansin
Nov 13 '18 at 9:10
add a comment |
Specifying the type in theXmlArrayItemAttribute
andXmlElementAttribute
is what fixed my issue, I will update my answer to show exactly what steps I took. Thanks so much!
– ryansin
Nov 13 '18 at 9:10
Specifying the type in the
XmlArrayItemAttribute
and XmlElementAttribute
is what fixed my issue, I will update my answer to show exactly what steps I took. Thanks so much!– ryansin
Nov 13 '18 at 9:10
Specifying the type in the
XmlArrayItemAttribute
and XmlElementAttribute
is what fixed my issue, I will update my answer to show exactly what steps I took. Thanks so much!– ryansin
Nov 13 '18 at 9:10
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53266907%2fdeserialize-class-properties-to-derived-class-instead-of-base-abstract-class%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
When working with weakly typed stuff (inlcuding unstable structured XML), there is the ExpandoObject class. Deserialize the XML into a ExpandoObject. Then later decide wich proper .NET class you translate it too, based on the values in the EO. That allows you to seperate the deserialization of the data and hte picking of the proper (sub) class.
– Christopher
Nov 12 '18 at 17:10
Can you edit your post to include the code that you are using to serialize and deserialize the objects?
– John Wu
Nov 12 '18 at 17:35
@JohnWu I have added that code as requested.
– ryansin
Nov 13 '18 at 8:23
@Christopher can you add an example of
ExpandoObject
please?– ryansin
Nov 13 '18 at 8:37