[翻译]XNA 3.0 Game Programming Recipes之thirtythree

PS:自己翻译的,转载请著明出处格
                                                  5-11 从一个XML文件中加载数据
问题
              你想从XML文件中加载数据到你的XNA游戏工程中。你可以做这个用从文件中读当你的XNA工程开始默认使用.NET文件的I/O功能函数,但是这是不会工作的,当你运行游戏在XBOX360控制台或者Zune.
              你想要XML文件被序列化成一个二进制文件通过内容管道,这样你能读数据载入到二进制文件在你的XNA工程中.
解决方案
              在XML文件中,简单的把对象你想加载在<XNAContent>和<Asset>标签之间,如在这个例子XML文件所描述一个自定义MapData类对象:
 1 <?xml version="1.0" encoding="utf-8"?>
 2   <XnaContent>
 3           <Asset Type="XMLDataPLine.MapData">
 4               <mapName>Battle In The Middle</mapName>
 5               <numberOfCastles>8</numberOfCastles>
 6               <allies>
 7                   <Item>Humans</Item>
 8                   <Item>Elves</Item>
 9                   <Item>Dwarves</Item>
10               </allies>
11           </Asset>
12    </XnaContent>
提示:如果你不知道如何创建一个XML文件自动从一个对象,你可以学习如何做这些在这章的结束.
               这XNA框架带有一个内容导入,能够把XML文件转化成类的对象定义在XML文件中.由于这个对象已经准备在这点完成,你不需要一个处理器,这个对象能立即被序列化成二进制文件.
               在这种情况,这个对象是自定义的MapData类,所以你必须定义一个自定义TypeWrite和TypeReader因为这是一个自定义类.
注意:如果XML文件描述一个类的对象,内容管道已经知道如何去序列化,你不必编写一个新的TypeWriter或者TypeReader.
               图5-22显示完整的原理图.

它是如何工作的
               导入一个.xml文件到你的XNA游戏工程中.在这个解决方案资源管理器,选择文件,这样它的属性被显示在屏幕的右下角.表明你想使用这默认的XML内容导入,来自XNA框架,和选择No Processing Required表明导入输出应该被序列化到一个文件没有通过一个处理器.图5-23显示最终的属性结果窗口:
               如果XML文件包含一个类的对象,内容管道知道如何去序列化和反序列化到/从一个二进制文件,你能立即加载这个对象到一个变量中在你的LoadContent方法中.在这节,无论如何,这MapData类是一个自定义类,所以你必须定义你的TypeWriter.
               添加一个新的内容管道对象到你的解决方案中通过10个步骤正如4-15节所解释的.这次,尽管,你不需要去定义你的自定义处理器.所有你需要去做的是定义一个MapData类,和一个适当的TypeWriter和TypeReader.
注意:确保你可以添加一个涉及到你的内容管道的工程,两个为内容入口和你的XNA工程,正如4-15节所解释的.它是被要求的,这样你的主要工程能访问MapData类的定义,它被存储在内容管道工程中.
定义一个自定义MapData类
               作为一个例子,这MapData类包含一个字符串,一个整型,一个字符串List.添加这定义到你的内容管道工程中:
1 public class MapData
2 {
3     public string mapName;
4     public int numberOfCastles;
5     public List<string> allies=new List<string>();
6 }  
提示:核实数据包含在前面的XML文件为这三个变量提供数据.
定义一个序列化一个MapData类的对象的能力
               正如4-15节所解释的那样,TypeWrite需要足够的数据准确的序列化从对象中,这样对象能在以后对重建通过TypeReader.一如往常,它同样可以提供TypeReader的位置去被使用:
 1 [ContentTypeWriter]
 2 public class MapDataTypeWriter:ContentTypeWriter<MapData>
 3 {
 4     protected override void Write(ContentWriter output,MapData value)
 5     {
 6         output.WriteObject<string>(value.mapName);
 7         output.WriteObject<int>(value.numberOfCastles);
 8         output.WriteObject<List<string>>(value.allies);
 9     }
10     public override string GetRuntimeReader(TargetPlatform targetPlatform)
11     {
12         return typeof(MapDataReader).AssemblyQualifiedName;
13     }
14 
                你定义这个TypeWriter将会序列化MapData类的对象的能力.这个默认内容管道知道如何去序列化一个字符串,一个整型,一个List,这样你简单的序列化她们到二进制文件.你传递一个连结到MapDataReaderTypeReader,下一步你会定义.
定义一个TypeReader序列化一个MapData类的对象的能力
                这个TypeReader简单的创建一个新的MapData对象;读取用字符串,整型,和List(用这正确的顺序!);保存它们在MapData对象的里面.填满对象返回和传送到XNA游戏工程中.
 1 class MapDataReader:ContentTypeReader<MapData>
 2 {
 3     protected override MapData Read(ContentReader input,MapData existingInstance)
 4     {
 5          MapData map=new MapData();
 6          map.mapName=input.ReadObject<string>();
 7          map.numberOfCastles=input.ReadObject<int>();
 8          map.allies=input.ReadObject<List<string>>();
 9          return map; 
10     }
11 }
用法
                第一行在这个LoadContent方法是足够去读在MapData对象在运行时.你将会插入第二行,它是一个断点在你的代码这样你能检查数据是实际上可用的:
1 protected override void LoadContent()
2 {
3     MapData loadedMap=Content.Load<MapData>("data");
4     System.Diagnostics.Debugger.Break();
5 }
                在最后一行的Break允许你去核查loadedMap变量包含值来自XML文件中.
注意:请记住,XML文件被转化成二进制文件时当你在编译你的工程时(使用F5).每当项目开始,只有TypeReader被调用到MapData对象结构从二进制文件中.意思是如果你改变XML文件的内容,你必须重新编译以应用于你的变化.
代码
               这个自定义内容管道包含唯一个类定义,TypeWriter,和TypeReader,它是你在这一章节很容易找到的。
课外阅读
创建一个XNA-Compatible XML文件从一个现有的对象中
               这节说明如何你能存储任何类的任何对象作为一个XML文件,你可以加载它使用默认的XML导入器.
               首先,你需要添加这些命名空间到你的使用的block中,这样你能使用它们的功能函数:
1 using System.Xml;
2 using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate;
               这些行的工作,你同样需要添加System.XMLMicrosoft.XNA.Framework.Content.Pipeline引用;你可以添加它们通过选择->添加引用.
                接下来,既不连接到你的自定义内容管道或者手动从新定义的MapData类通过把这些代码外置到你工程的命名空间:
1 namespace XMLDataPLine
2 {
3     public class MapData
4     {
5         public string mapName;
6         public int numberOfCastles;
7         public List<string> allies=new List<string>();
8     }
9 }

                如果你重新定义手动的类,确保你把它放在同样命名空间内作为你自定义内容管道(我的被称为XMLDataPLine)和所有的变量是相同的.
                接下来,回到你的XNA工程的命名空间,确保你已经有一个MapData类的对象:

1 XMLDataPLine.MapData myMap=new XMLDataPLine.MapData();
2 myMap.mapName="Battle In The Middle";
3 myMap.numberOfCastles=8;
4 myMap.allies.Add("Humans");
5 myMap.allies.Add("Elves");
6 myMap.allies.Add("Dwarves");
                使用这个代码去保存它到一个XNA-compatible XML文件中,称为data.xml:
1 string fileName="data.xml";
2 XmlWriter writer=XmlWriter.Create(fileName);
3 IntermediateSerializer.Serialize<XMLDataPLine.MapData>(writer,myMap,fileName);
4 writer.Close();
               当你运行这个程序,data.xml文件将会被创建在图上,这里是你加载.exe的地方.
注意:你同样也可以在这个例子中找到代码
原文地址:https://www.cnblogs.com/315358525/p/1541691.html