在XML序列化时,如何设置xsi:type ?

blackfire1024 2009-04-13 01:30:59
比如我要设计一个Test类
在序列化时能有xsi:type
该如何写?


<?xml version="1.0"?>
<Root>
<Test name="a" xsi:type="Day" />
<Test name="b" xsi:type="Month" />
<Test name="c" xsi:type="Year" />
</Root>


利用 XmlAttribute 属性好像不能设置xsi:type

又查了下 MSDN

发现存在 XmlSerializationWriter类,其中有 WriteXsiType 方法

但MSDN同时建议:此 API 支持 .NET Framework 基础结构,不适合在代码中直接使用。

那该如何设置他才能自动序列化?

请熟练XML序列化的朋友指点


...全文
1754 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
orain 2009-04-13
  • 打赏
  • 举报
回复
不对,反序列化还是有问题,我上面的推断看来不正确.
orain 2009-04-13
  • 打赏
  • 举报
回复
呵呵,我做的时候也觉得是取巧来着,当时我还奇怪一个 Test 元素怎么会对应着那么多类型,因为好久没接触 XML,所以自己也没把握.所以就硬做了一个出来:)
其实你的第二个问题主要是命名空间冲突了,这样可以看得更明显一些:
[XmlInclude(typeof(Manager))]
[XmlType(Namespace="http://www.w3.org/2001/XMLSchema-instance")] //这一句
[Serializable]
public class Employee
{
[XmlAttribute]
public string Name;
}

这样的话就不用改这一句了:
XmlSerializer xs = new XmlSerializer(typeof(Group));
我觉得 XML 最烦的就是命名空间了,规则太多,老搞不清楚.幸好用得也不多.
blackfire1024 2009-04-13
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 orain 的回复:]
XmlSerializer xs = new XmlSerializer(typeof(Group), "http://www.csdn.net");
[/Quote]

3Q 完美解决
blackfire1024 2009-04-13
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 orain 的回复:]
C# codeclass Program
{
static void Main()
{
List<Test> tests = new List<Test>();
tests.Add(new Test("a", "Day"));
tests.Add(new Test("b", "Month"));
tests.Add(new Test("c", "Year"));

XmlSerializer xs = new XmlSerializer(typeof(List<Test>));
xs.Serialize(Console.Out, tests);
}
}

public class Test
{
[XmlAttri…
[/Quote]


这个方法有点投机...

但是 我要的是 xsi:type

如果把 Type 改成 type

那么在反序列化的时候 会失败

请看代码


class Program
{
static void Main()
{
List<Test> tests = new List<Test>();
tests.Add( new Test( "a", "Day" ) );
tests.Add( new Test( "b", "Month" ) );
tests.Add( new Test( "c", "Year" ) );

string filename = @"C:\temp.txt";
XmlSerializer xs = new XmlSerializer( typeof( List<Test> ) );
using ( FileStream fs = new FileStream( filename, FileMode.Create ) )
{
xs.Serialize( fs, tests );
}

using ( FileStream fs = new FileStream( filename, FileMode.Open ) )
{
tests = xs.Deserialize( fs ) as List<Test>;
foreach ( Test test in tests )
{
Console.WriteLine( test.Name + " " + test.Type );
}
}

Console.ReadLine();
}
}

public class Test
{
[XmlAttribute( AttributeName = "name" )]
public string Name { get; set; }
[XmlAttribute( AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance" )] //要正确设置 Namespace
public string Type { get; set; }

public Test() { }
public Test( string name, string type )
{
Name = name;
Type = type;
}
}
orain 2009-04-13
  • 打赏
  • 举报
回复
XmlSerializer xs = new XmlSerializer(typeof(Group), "http://www.csdn.net");
blackfire1024 2009-04-13
  • 打赏
  • 举报
回复
xsi:type的问题已解决

只要使用泛型进行序列化就可以达到效果



但又有新问题了

若在XmlRoot属性指定了NameSpace
则泛型序列化就会失败

代码如下:

using System;
using System.IO;
using System.Xml.Serialization;

[Serializable]
[XmlRoot( Namespace = "http://www.csdn.net" )]
public class Group
{
public List<Employee> Employees = new List<Employee>();
}

[XmlInclude( typeof( Manager ) )]
[Serializable]
public class Employee
{
[XmlAttribute]
public string Name;
}

[Serializable]
public class Manager : Employee
{
[XmlAttribute]
public int Level;
}


public class Run
{
public static void Main()
{
Run test = new Run();
string path = @"D:\Temp\xsitype.txt";
test.SerializeObject( path );
test.DeserializeObject( path );
}


public void SerializeObject( string filename )
{
using ( FileStream fs = new FileStream( filename, FileMode.Create ) )
{
XmlSerializer s = new XmlSerializer( typeof( Group ) );
TextWriter writer = new StreamWriter( fs );
Group group = new Group();

Manager manager = new Manager();
Employee emp1 = new Employee();
Employee emp2 = new Employee();

manager.Name = "Zeus";
manager.Level = 2;

emp1.Name = "Ares";

emp2.Name = "Artemis";

group.Employees.Add( manager );

s.Serialize( writer, group);
}
}

public void DeserializeObject( string filename )
{
FileStream fs = new FileStream( filename, FileMode.Open );
XmlSerializer x = new XmlSerializer( typeof( Group ) );
Group g = ( Group ) x.Deserialize( fs );
Console.Write( "Members:" );

foreach ( Employee e in g.Employees )
{
Console.WriteLine( "\t" + e.Name );
}
Console.ReadLine();
}
}


错误内容为 “不应是类型 xxxxxx.Manager。使用 XmlInclude 或 SoapInclude 属性静态指定非已知的类型。”

但我已经设置了XmlInclude 如果把NameSpace去除,则运行正常

请问该如何设置
orain 2009-04-13
  • 打赏
  • 举报
回复
class Program
{
static void Main()
{
List<Test> tests = new List<Test>();
tests.Add(new Test("a", "Day"));
tests.Add(new Test("b", "Month"));
tests.Add(new Test("c", "Year"));

XmlSerializer xs = new XmlSerializer(typeof(List<Test>));
xs.Serialize(Console.Out, tests);
}
}

public class Test
{
[XmlAttribute(AttributeName="name")]
public string Name { get; set; }
[XmlAttribute(AttributeName="Type", Namespace="http://www.w3.org/2001/XMLSchema-instance")] //要正确设置 Namespace
public string Type { get; set; }

public Test() { }
public Test(string name, string type)
{
Name = name;
Type = type;
}
}

111,080

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧