XML deserialization of generic element types

Suppose I have the following class:

public abstract class ScheduledService : ScheduledServiceBase<ScheduledService>
{
    public CronInfo CronInfo;
    public String ServiceName;

    public ScheduledService()
    { }
}

public abstract class ScheduledServiceBase<T>
{
    public ScheduledServiceBase()
    { }

    public virtual void StartUp(IScheduler scheduler, ScheduledService service, Dictionary<string, object> parameters = null)
    {
        ...
    }
}

From this base class, I create two inheriting classes, for example:

public AlphaService : ScheduledService 
{
    public String Alpha_Name;
    public Int32  Alpha_Age;

    public AlphaService() { }
}

public BetaService : ScheduledService 
{
    public String  Beta_Company;
    public Boolean Beta_IsOpen;

    public AlphaService() { }
}

Then, in my XML, I define two services:

  <ScheduledServices>
    <AlphaService>
      <Alpha_Name>John Jones</Alpha_Name>
      <Alpha_Age>32</Alpha_Age>
      <ServiceName>FirstService</ServiceName>
      <CronInfo>0 0 0/2 * * ? *</CronInfo>
    </AlphaService>
    <BetaService>
      <Beta_Company>Ajax Inc.</Beta_Company>
      <Beta_IsOpen>Ajax Inc.</Beta_IsOpen>
      <ServiceName>SecondService</ServiceName>
      <CronInfo>0 30 0/5 * * ? *</CronInfo>
    </BetaService>
  </ScheduledService>

When I deserialize this, I try to assign ScheduledServices List<ScheduledService> ScheduledServices, but after deserialization, nothing exists in the list. Deserializer does not throw an error, it just does not create any services.

Is what I'm trying to make valid, or do I need to configure services differently?

Here is what I use for XML deserialization:

public Boolean Load(params Type[] extraTypes)
{
    deserializedObject = default(T);
    XmlTextReader reader = null;

    try
    {
        reader = new XmlTextReader(new StreamReader(_actualPath));
        XmlSerializer serializer = new XmlSerializer(typeof(T), extraTypes);
        deserializedObject = (T)(serializer.Deserialize(reader));
    }
    catch (Exception ex)
    {
        log.Error("Error: " + ex.Message);
        log.Debug("Stack: " + ex.StackTrace);
        log.Debug("InnerException: " + ex.InnerException.Message);
    }
    finally
    {
        if (reader != null) reader.Close();
    }
    return ((this.deserializedObject != null) && deserializedObject is T);
}

Decision

Thanks to John Arlene and his example and a link to another post, I was able to do what I wanted by creating a list as follows:

    [XmlArrayItem("AlphaJob", Type=typeof(AlphaJob))]
    [XmlArrayItem("BetaJob", Type=typeof(BetaJob))]
    public List<ScheduledService> ScheduledServices;
+4
source share
1

XmlSerializer , XML .

, , "AlphaService" ( "MyNamespace.AlphaService, MyUtility"?)

- XmlSerializer.Serialize(myObj), , .

XML, ( XmlElementAttribute, )

EDIT: :

[XmlInclude( typeof( AlphaService ) )]
[XmlInclude( typeof( BetaService ) )]
    public abstract class ScheduledService : ScheduledServiceBase<ScheduledService> {...}

, XML :

private void SerializeAndBack()
{
    var item = new ScheduledServiceHost
        {
            ScheduledServices = new List<ScheduledService>
                {
                    new AlphaService {Alpha_Age = 32, Alpha_Name = "John Jones", ServiceName = "FirstService"},
                    new BetaService {Beta_Company = "Ajax Inc.", Beta_IsOpen = true, ServiceName = "SecondService"},
                }
        };

    var xmlText = XmlSerializeToString( item );
    var newObj = XmlDeserializeFromString( xmlText, typeof( ScheduledServiceHost ) );
}

public static string XmlSerializeToString( object objectInstance, params Type[] extraTypes )
{
    var sb = new StringBuilder();

    using ( TextWriter writer = new StringWriter( sb ) )
    {
        var serializer = new XmlSerializer( objectInstance.GetType(), extraTypes );
        serializer.Serialize( writer, objectInstance );
    }

    return sb.ToString();
}

public static object XmlDeserializeFromString( string objectData, Type type )
{
    using ( var reader = new StringReader( objectData ) )
    {
        return new XmlSerializer( type ).Deserialize(reader);
    }
}

SO .

+3

Source: https://habr.com/ru/post/1542370/


All Articles