I am using .NET 4.52. I am programming in VB.NET, but if you have a solution in C#, I can transpose.
I have an entire class library, which has a bunch of complex types, etc which represent different messages in our system which I can't change. Depending on the Message_Type (an attribute in the XMLRoot) different attributes and elements are required. If I try to deserialize an object that has the wrong info, it does not throw an exception, and I want it to. XSD validation does not work because often the element name is the same for two different types, but each type requires different stuff. Using XMLAttribute and XMLElement tags on my classes, there is no "Required" property. Even though there is a "IsNullable" property on Elements (but not Attributes), the XMLSerializer seems to pay no attention to this during deserialization.
So, I decided that I would try to create an additional "Required" attribute:
<AttributeUsage(AttributeTargets.Property, Inherited:=False, AllowMultiple:=False)>
Public Class XMLPlusElementAttribute
Inherits XmlElementAttribute
Public Sub New()
MyBase.ElementName = ElementName
Me.m_Required = False
End Sub
Private m_Required As Boolean
Public Overridable Property Required() As Boolean
Get
Return m_Required
End Get
Set(value As Boolean)
m_Required = value
End Set
End Property
End Class
<AttributeUsage(AttributeTargets.Property, Inherited:=False, AllowMultiple:=False)>
Public Class XMLPlusAttributeAttribute
Inherits XmlAttributeAttribute
Public Sub New()
MyBase.AttributeName = AttributeName
Me.m_Required = False
End Sub
Private m_Required As Boolean
Public Overridable Property Required() As Boolean
Get
Return m_Required
End Get
Set(value As Boolean)
m_Required = value
End Set
End Property
End Class
I can now decorate my classes with them:
<Serializable>
<XmlRoot("INTERFACE")>
Public MustInherit Class WM_Interface
Private m_Message_Type As String
Private m_Event_DTTM As String
Private m_Business_Unit As String
<XMLPlusAttribute(AttributeName:="MESSAGE_TYPE", Required:=True)>
Public Property Message_Type() As String
Get
Return m_Message_Type
End Get
Set(value As String)
m_Message_Type = value
End Set
End Property
<XMLPlusAttribute(AttributeName:="EVENT_DTTM", Required:=True)>
Public Property Event_DTTM() As String
Get
Return m_Event_DTTM
End Get
Set(value As String)
m_Event_DTTM = value
End Set
End Property
<XMLPlusAttribute(AttributeName:="BUSINESS_UNIT", Required:=True)>
Public Property Business_Unit() As String
Get
Return m_Business_Unit
End Get
Set(value As String)
m_Business_Unit = value
End Set
End Property
End Class
<Serializable>
<XmlRoot("INTERFACE")>
Public Class WM_Interface_BOX
Inherits WM_Interface
Private m_Container As WM_Container_BOX
<XMLPlusElement(ElementName:="CONTAINER", IsNullable:=False, Required:=True)>
Public Property Container() As WM_Container_BOX
Get
Return m_Container
End Get
Set(value As WM_Container_BOX)
m_Container = value
End Set
End Property
End Class
<Serializable>
<XmlRoot("INTERFACE")>
Public Class WM_Interface_FIB
Inherits WM_Interface
Private m_Fiber As WM_Fiber
<XMLPlusElement(ElementName:="FIBER", IsNullable:=False, Required:=True)>
Public Property Fiber() As WM_Fiber
Get
Return m_Fiber
End Get
Set(value As WM_Fiber)
m_Fiber = value
End Set
End Property
End Class
So the question now is how to customize the serialization / deserialization process to make use of this new "Required" attribute. If I inherit XMLSerializer, I can seemingly override the methods, but I am not sure what to put in there:
Public Class XMLPlusSerializer
Inherits XmlSerializer
Protected Overrides Function Deserialize(reader As XmlSerializationReader) As Object
Return MyBase.Deserialize(reader)
End Function
Protected Overrides Sub Serialize(o As Object, writer As XmlSerializationWriter)
MyBase.Serialize(o, writer)
End Sub
End Class
I know I can also implement ISerializable and write custom ReadXML() and WriteXML() methods for each, but I want something way more generic. Any help or guidance you can suggest will be greatly appreciated!