XML反序列化泛型类型的项

时间:2014-05-28 18:04:22

标签: c# xml deserialization

假设我有以下课程:

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)
    {
        ...
    }
}

从这个基类我创建了两个继承类,如:

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() { }
}

然后在我的XML中我定义了两个服务:

  <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>

当我反序列化时,我试图将ScheduledServices分配给List<ScheduledService> ScheduledServices,但反序列化后列表中不存在任何内容。解串器不会出错,它不会创建任何服务。

我想要做的是有效还是我需要以不同方式设置服务?

以下是我用来反序列化XML的内容:

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);
}

感谢John Arlen和他的示例以及其他帖子的链接,我可以通过创建列表来完成我想要的操作,如下所示:

    [XmlArrayItem("AlphaJob", Type=typeof(AlphaJob))]
    [XmlArrayItem("BetaJob", Type=typeof(BetaJob))]
    public List<ScheduledService> ScheduledServices;

1 个答案:

答案 0 :(得分:3)

XmlSerializer类需要比XML提供的更多信息才能正常工作。

例如,它并不确切地知道&#34; AlphaService&#34; (&#34; MyNamespace.AlphaService,MyUtility&#34;?)

最简单的方法是在内存中创建一个示例对象,并调用XmlSerializer.Serialize(myObj)来了解它正在寻找的实际格式。

如果您无法控制传入的XML,则需要进一步修饰您的类(例如,使用XmlElementAttribute),或使用其他机制

编辑:标记您的课程的示例可能是:

[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);
    }
}
关于标记类的一些选项的

Here is a good SO answer是。