Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# XML序列化:反序列化抽象属性时出现问题_C#_.net_Xml Serialization - Fatal编程技术网

C# XML序列化:反序列化抽象属性时出现问题

C# XML序列化:反序列化抽象属性时出现问题,c#,.net,xml-serialization,C#,.net,Xml Serialization,我仍在试图把我的头脑集中在整个xml序列化的事情上,似乎我再次需要一些帮助 我需要能够反序列化抽象类型的属性。随着时间的推移,此类型将添加许多不同的具体类型,并且在许多不同的模型中引用,因此显式列出每个具体类型并不是理想的解决方案 我已经阅读了这篇文章,并得出以下结论: <Page> <introCommand> <PlayElement /> </introCommand> </Page> ** ** 命名空间测试服

我仍在试图把我的头脑集中在整个xml序列化的事情上,似乎我再次需要一些帮助

我需要能够反序列化抽象类型的属性。随着时间的推移,此类型将添加许多不同的具体类型,并且在许多不同的模型中引用,因此显式列出每个具体类型并不是理想的解决方案

我已经阅读了这篇文章,并得出以下结论:

<Page>
  <introCommand>
    <PlayElement />
  </introCommand>
</Page>
**

**

命名空间测试服务
{
公共类XmlCommandSerializer:IXmlSerializable
{
//重写自XmlSerializer之后的隐式转换
//隐式转换到所需类型或从所需类型转换。
公共静态隐式运算符AbstractCommandModel(XmlCommandSerializer o)
{
返回o.数据;
}
公共静态隐式运算符XmlCommandSerializer(AbstractCommando模型)
{
返回o==null?null:新的XmlCommandSerializer(o);
}
私有抽象模型数据;
/// 
///[具体]要存储的数据/存储为XML。
/// 
公共抽象模型数据
{
获取{return_data;}
设置{u data=value;}
}
/// 
///**不要使用**这只是为了启用XML序列化而添加的。
/// 
///不要使用此构造函数
公共XmlCommandSerializer()
{
//默认Ctor(Xml序列化所需-不使用)
}
/// 
///初始化序列化程序以使用给定数据。
/// 
///指定的AbstractCommandModel的具体对象。
公共XmlCommandSerializer(AbstractCommandModel数据)
{
_数据=数据;
}
#区域IXmlSerializable成员
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;//由于架构未知,因此这没有问题。
}
public void ReadXml(System.Xml.XmlReader)
{
//从抽象类型强制转换回数据。
字符串typeAttrib=reader.GetAttribute(“类型”);
//确保已指定类型
if(typeAttrib==null)
抛出新ArgumentNullException(“无法读取抽象类型的Xml数据””+typeof(AbstractCommandModel)。Name+
“,因为XML中没有指定“type”属性。”);
Type Type=Type.GetType(typeAttrib);
//检查是否找到类型。
if(type==null)
抛出新的InvalidCastException(“无法读取抽象类型的Xml数据””+typeof(AbstractCommandModel)。Name+
“'因为找不到XML中指定的类型。“);
//检查类型是否为AbstractCommandModel的子类。
if(!type.IsSubclassOf(typeof(AbstractCommandModel)))
抛出新的InvalidCastException(“无法读取抽象类型的Xml数据””+typeof(AbstractCommandModel)。Name+
“,因为XML中指定的类型不同(“+Type.Name+”)”);
//读取数据,根据(现在已知的)具体类型进行反序列化。
reader.ReadStartElement();
this.Data=(AbstractCommandModel)新建
XmlSerializer(类型)。反序列化(读取器);
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter)
{
//将类型名作为Attrib写入XML元素并序列化
类型类型=_data.GetType();
//错误修复:程序集必须是FQN,因为类型可以/是当前的外部类型。
WriteAttributeString(“类型”,类型.AssemblyQualifiedName);
新的XmlSerializer(类型).Serialize(写入程序,_数据);
}
#端区
}
}
然而,当我运行反序列化程序时,我得到一个InvalidOperationException,声明“XML文档(3,3)中有一个错误”。与前面提到的线程中的示例相比,我唯一改变的是类名

我做得对吗?如果是,是什么导致了这个错误?

来自您的示例:

//[XmlElement(typeof(PlayElement))] **NOTE: the example works if I use this instead
这是支持抽象类的推荐方法。您可以按元素名称切换实例,并使用如下多个声明:

[XmlElement("playElement", typeof(PlayElement))]
[XmlElement("testElement", typeof(TestElement))]
public AbstractCommandModel Command;
当然,您仍然需要删除“introCommand”元素或添加另一个类来嵌套上述声明

如果您仍然需要手动执行序列化,那么您的路径是正确的。我想,您的示例运行得很好,下面是XML输出:

<Page>
  <introCommand type="TestService.PlayElement, TestService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
    <PlayElement />
  </introCommand>
</Page>
从你的例子来看:

//[XmlElement(typeof(PlayElement))] **NOTE: the example works if I use this instead
这是支持抽象类的推荐方法。您可以按元素名称切换实例,并使用如下多个声明:

[XmlElement("playElement", typeof(PlayElement))]
[XmlElement("testElement", typeof(TestElement))]
public AbstractCommandModel Command;
当然,您仍然需要删除“introCommand”元素或添加另一个类来嵌套上述声明

如果您仍然需要手动执行序列化,那么您的路径是正确的。我想,您的示例运行得很好,下面是XML输出:

<Page>
  <introCommand type="TestService.PlayElement, TestService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
    <PlayElement />
  </introCommand>
</Page>

这就是为什么我很久以前放弃了XamlServices的XmlSerializer和NetDataContractSerializer。@XamlServices看起来会更接近我所需要的吗。实际上,整个目的是从XML结构构造复杂的对象图。缺点是这需要对XML进行大量重构才能工作。这不是不可能的,但也不完全理想。我得再仔细研究一下,我明白这是怎么回事。但很高兴知道,在未来,XmlSerializer还有许多新的替代品。这就是为什么我很久以前放弃了XmlSerializer用于XamlServices和NetDataContractSerializer的原因。@XamlServices看起来会更接近我的需要吗。事实上,整个目的是为了
<Page>
  <introCommand type="TestService.PlayElement, TestService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
    <PlayElement />
  </introCommand>
</Page>
    private static void Main()
    {
        StringWriter dataOut = new StringWriter();
        XmlTextWriter writer = new XmlTextWriter(dataOut);
        writer.Formatting = Formatting.Indented;

        Page p = new Page();
        p.introCommand = new PlayElement();

        new XmlSerializer(typeof(Page)).Serialize(writer, p);
        string xml = dataOut.ToString();
        Console.WriteLine(xml);

        XmlTextReader reader = new XmlTextReader(new StringReader(xml));
        Page copy = (Page) new XmlSerializer(typeof (Page)).Deserialize(reader);
    }