无法在C#中反序列化XML-InvalidOperationException

时间:2018-07-03 15:42:57

标签: c# xml xmlserializer

我有一个C#应用,该应用在App.config文件中具有自定义部分的配置信息。目前,我可以通过代码成功加载自定义信息。但是,我也试图从数据库中加载相同的配置信息。为了做到这一点,我从我知道可以正常工作的App.config文件中提取了XML字符串。该XML字符串如下所示:

<departments>
  <department id="1" name="Sporting Goods">
    <products>
      <product name="Basketball" price="9.99">
        <add key="Color" value="Orange" />
        <add key="Brand" value="[BrandName]" />
      </product>
    </products>
  </department>
</departments>

我正在尝试将此XML反序列化为C#对象。我已经定义了这些对象,如下所示:

Departments.cs

public class Departments : ConfigurationSection
{
  private Departments() { }

  [ConfigurationProperty("", IsRequired = false, IsKey = false, IsDefaultCollection = true)]
  public DepartmentItemCollection Items
  {
    get
    {
      var items = base[""] as DepartmentItemCollection;
      return items;
    }
    set { base["items"] = value; }
  }

  public static Departments Deserialize(string xml)
  {
    Departments departments = null;

    var serializer = new XmlSerializer(typeof(Departments));
    using (var reader = new StringReader(xml))
    {
      departments = (Departments)(serializer.Deserialize(reader));
    }

    return departments;
  }
}

[ConfigurationCollection(typeof(Department), CollectionType = ConfigurationElementCollectionType.BasicMapAlternate)]
public class DepartmentItemCollection : ConfigurationElementCollection
{
  private const string ItemPropertyName = "department";

  public override ConfigurationElementCollectionType CollectionType
  {
    get { return ConfigurationElementCollectionType.BasicMapAlternate; }
  }

  protected override string ElementName
  {
    get { return ItemPropertyName; }
  }

  protected override bool IsElementName(string elementName)
  {
    return (elementName == ItemPropertyName);
  }

  protected override object GetElementKey(ConfigurationElement element)
  {
    return ((Department)element).Name;
  }

  protected override ConfigurationElement CreateNewElement()
  {
    return new Department();
  }

  public override bool IsReadOnly()
  {
    return false;
  }
}

Department.cs

public class Department : ConfigurationElement
{
  public Department()
  { }

  [ConfigurationProperty("id", IsRequired = false, IsKey = true)]
  public int Id
  {
    get { return (int)(this["id"]); }
    set { this["id"] = value; }
  }

  [ConfigurationProperty("name", IsRequired = true, IsKey = true, DefaultValue = "")]
  public string Name
  {
    get { return (string)(this["name"]); }
    set { this["name"] = value; }
  }

  [ConfigurationProperty("products", IsRequired = false, IsKey = false, IsDefaultCollection = false)]
  public ProductCollection Products
   {
     get { return ((ProductCollection)(base["products"])); }
     set { base["products"] = value; }
   }
}

DepartmentProducts.cs

[ConfigurationCollection(typeof(Product), AddItemName = "product", CollectionType = ConfigurationElementCollectionType.BasicMapAlternate)]
public class ProductCollection: ConfigurationElementCollection
{
    public override ConfigurationElementCollectionType CollectionType
    {
        get { return ConfigurationElementCollectionType.BasicMapAlternate; }
    }

    protected override string ElementName
    {
        get { return string.Empty; }
    }

    protected override bool IsElementName(string elementName)
    {
        return (elementName == "product");
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return element;
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new Product();
    }

    protected override ConfigurationElement CreateNewElement(string elementName)
    {
        var product = new Product();
        return product;
    }

    public override bool IsReadOnly()
    {
        return false;
    }
}

DepartmentProduct.cs

public class Product : ConfigurationElement
{
  public Product()
  { }

  [ConfigurationProperty("name", IsRequired = true, IsKey = true, DefaultValue = "")]
  public string Name
  {
    get { return (string)(this["name"]); }
    set { this["name"] = value; }
  }

  [ConfigurationProperty("price", IsRequired = false)]
  public decimal Price
  {
    get { return (decimal)(this["price"]); }
    set { price["name"] = value; }
  }

  [ConfigurationProperty("", IsRequired = false, IsKey = false, IsDefaultCollection = true)]
  public KeyValueConfigurationCollection Items
  {
    get
    {
      var items = base[""] as KeyValueConfigurationCollection;
      return items;
    }
    set { base["items"] = value; }
  }
}

当我将上面显示的XML传递给Departments.Deserialize方法时,收到以下错误:

InvalidOperationException:您必须在System.Configuration.ConfigurationLockCollection上实现默认访问器,因为它继承自ICollection。

如何将共享的XML反序列化为共享的C#对象?

1 个答案:

答案 0 :(得分:1)

我过去也有类似的问题。尽管我不知道该如何处理InvalidOperationException,但我还是通过直接将类标记为IXmlSerializable

来使其正常工作
 [XmlRoot("departments")]
 public class Departments : ConfigurationSection, IXmlSerializable
 {
    //Your code here..

    public XmlSchema GetSchema()
    {
        return this.GetSchema();
    }

    public void ReadXml(XmlReader reader)
    {
        this.DeserializeElement(reader, false);
    }

    public void WriteXml(XmlWriter writer)
    {
        this.SerializeElement(writer, false);
    }
 }