Невозможно десериализовать XML в C # - InvalidOperationException - PullRequest
0 голосов
/ 03 июля 2018

У меня есть приложение на C #, в котором есть настраиваемый раздел информации о конфигурации в файле App.config. В настоящее время я могу успешно загрузить пользовательскую информацию с помощью кода. Тем не менее, я пытаюсь загрузить ту же информацию о конфигурации из базы данных. В попытке сделать это я взял строку XML из моего файла App.config, который, как я знаю, работает. Эта строка 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 голосов
/ 06 июля 2018

У меня была похожая проблема в прошлом. Хотя я не мог понять, что делать с 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);
    }
 }
...