反序列化和构造函数关系

deserialize and constructor relationship

我不知道为什么我不能在网上找到一个简单的快速查找,但我想知道反序列化一个对象的 XML 表示和它的构造函数之间的关系是什么目的?

我假设它使用默认构造函数。如果是这种情况,它将 运行 构造函数中的代码,但之后不会更新对象本身以反映 XML?

这里有更多关于我的意思的上下文...

我有一个对象,它有两个实际上也是对象的属性:

public class Deployment
{
    public AppPoolSettings AppPool { get; set; }
    public WebSiteSettings Site { get; set; }

    public Deployment()
    {
        //the object constructors below init their internal properties as well...
        this.AppPool = new AppPoolSettings();
        this.Site = new WebSiteSettings();
    }
}

我目前遇到的问题是,在 XML 中,AppPool 属性 可以为空(例如,如果您仅部署 HTML包裹)。序列化程序正常工作,也就是说,生成的 XML 仅包含 Site 的条目,而没有 AppPool 的条目。

然而,当我反序列化那个 XML 时,我的 Deployment 对象的 AppPool 属性 总是被实例化和初始化......这不是 XML在说。

是我做错了什么还是真的只是因为默认构造函数?

看吧,我希望反序列化器按以下顺序执行任务:
1-调用默认构造函数
2- AppPool 属性 是否存在于 XML 中?
是 --> 填写,
否 --> 设置为 NULL
3- 站点 属性 是否存在于 XML 中?
是 --> 填写,
否 --> 设置为 NULL

为什么不这样做?

我相信正确答案是:是的,对空属性的违反直觉的处理(在序列化数据中省略它们并且在反序列化时不对它们进行任何处理)是 XmlSerializer.但是您可以覆盖该行为并强制 XmlSerializer 将空值写入 XML 并具有如下属性:

public class Deployment
{
    [XmlElement(IsNullable = true)]
    public AppPoolSettings AppPool { get; set; }
    [XmlElement(IsNullable = true)]
    public WebSiteSettings Site { get; set; }

    public Deployment()
    {
        //the object constructors below init their internal properties as well...
        this.AppPool = new AppPoolSettings();
        this.Site = new WebSiteSettings();
    }
}

然后您将在 XML 中得到 <AppPool xsi:nil="true" /> 和预期的反序列化。

调用了默认构造函数,因此分配了 Site 和 AppPool。如果你想让它们成为 null 也许你可以试试这个代码:

public class Deployment
{
     private AppPoolSettings appPool;

     public AppPoolSettings AppPool
     {
         get { return appPool; }
         set
         {
             // if (appPool == null)
             //    appPool = new AppPoolSettings();
             appPool = value;
         }
     }

     private WebSiteSettings site;

     public WebSiteSettings Site
     {
         get { return site; }
         set
         {
             // if (site == null)
             //    site = new WebSiteSettings();
             site = value;
         }
     }

     public Deployment()
     {
         // No instatiation anymore...         
     }
 }

你的期望是错误的。 XmlSerializer 将构造对象(通过调用无参数构造函数,如果有 none - 抛出异常)。然后属性将使用一些反射魔法一一填充。

那么会发生什么:

  1. 构造函数被调用,在其中设置 AppPoolSite 的值。

  2. xml中有Site属性,反序列化赋值

  3. 但是xml中没有AppPool,所以没有任何变化,它的值保持不变(不是null)。

要让 null 对应 AppPool,您不应该在构造函数中设置它的值。如果在 xml.

中丢失,它将保持这样

这是一种可能的解决方案:

public class Deployment
{
    public AppPoolSettings AppPool { get; set; }
    public WebSiteSettings Site { get; set; }

    // used by deserializer
    public Deployment() { }

    // use this to construct object
    public static Deployment Create()
    {
        return new Deployment()
        {
            AppPool = new AppPoolSettings(),
            Site = new WebSiteSettings()
        };
    }
}