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

标签 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# 对象?

最佳答案

我以前遇到过类似的问题。虽然我不知道如何处理 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);
    }
 }

关于c# - 无法在 C# 中反序列化 XML - InvalidOperationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51158503/

相关文章:

c# - 我的存储过程返回了一些东西,但是 sqlDataAdapter.Fill 将数据表留空

java - 为什么 Adapter 多次向 ListView 添加相同的位置?

php - simplexml_load_string() 将空 xml 元素转换为对象而不是字符串

java - XMLSerializer 和 OutputFormat 已弃用

c# - 如何在asp.net 的转发器控件栏中显示图像?

c# - 如何将动态对象传递给 HtmlHelper.Editor()?

.net - 使用XmlSerializer时如何忽略派生类中基类的属性?

.net - XMLSrializer 中的 IDeserializationCallback

c# - 在 C# 中将复杂对象绑定(bind)到 DataTable 的单元格

java - 解析 XML,跳过某些标签