2014-07-14 64 views
0

我使用下面的访问者模式代码解析的XML文件:访问者模式循环问题

using RimWorld; 
using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using UnityEngine; 
using Verse; 

namespace ColonistCreationMod 
{ 
class LoadColonists 
{ 
    public static void LoadFromFile(Map map, string groupName) 
    { 
     try 
     { 
      string path = Directory.GetParent(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)).FullName; 
      if (Environment.OSVersion.Version.Major >= 6) 
      { 
       path = Directory.GetParent(path).FullName; 
      } 
      path += "\\AppData\\LocalLow\\Ludeon Studios\\RimWorld\\CharSaves\\" + groupName + ".col"; 
      ColonistRegen(path); 
      Parse(path); 
     } 
     catch (Exception e) 
     { 
      Log.Message(e.Message); 
     } 
     GC.Collect(); 
    } 

    private static void ColonistRegen(string file) 
    { 
     using (XmlTextReader reader = new XmlTextReader(File.OpenRead(file))) 
     { 
      while (reader.Read()) 
      { 
       switch (reader.Name) 
       { 
        case "ColonistAmount": 
         ColonistNum.Amount = VisitAmount(reader); 
         ColonistManager.RandomColonists(); 
         ModdedMapInitParams.GenerateColonists(); 
         break; 
       } 
      } 
     } 
    } 

    private static int VisitAmount(XmlTextReader reader) 
    { 
     int amount = 0; 
     while (reader.MoveToNextAttribute()) 
     { 
      switch (reader.Name) 
      { 
       case "amount": 
        amount = int.Parse(reader.Value); 
        break; 
      } 
     } 

     return amount; 
    } 

    private static void Parse(string file) 
    { 
     using (XmlTextReader reader = new XmlTextReader(File.OpenRead(file))) 
     { 
      int i = 0; 
      while (reader.Read()) 
      { 
       switch (reader.Name) 
       { 
        case "Colonist": 
         Log.Message("Colonist: " + i.ToString()); 
         VisitColonist(reader, i); 
         i++; 
         break; 
       } 
      } 
     } 
    } 

    private static void VisitColonist(XmlTextReader reader, int i) 
    { 
     while (reader.Read()) 
     { 
      if (reader.Name == "Colonist" && reader.NodeType == XmlNodeType.EndElement) 
       break; 

      switch (reader.Name) 
      { 
       case "BasicInfo": 
        VisitBasicInfo(reader, i); 
        break; 

       case "Graphics": 
        VisitGraphics(reader, i); 
        break; 

       case "HairDef": 
        VisitHairDef(reader, i); 
        break; 

       case "OnSkin": 
        VisitOnSkin(reader, i); 
        break; 

       case "Shell": 
        VisitShell(reader, i); 
        break; 

       case "Childhood": 
        VisitChildhood(reader, i); 
        break; 

       case "Adulthood": 
        VisitAdulthood(reader, i); 
        break; 

       case "SkillPool": 
        VisitSkillPool(reader, i); 
        break; 

       case "Skills": 
        VisitSkills(reader, i); 
        break; 
      } 
     } 
    } 

    private static void VisitBasicInfo(XmlTextReader reader, int i) 
    { 
     while (reader.MoveToNextAttribute()) 
     { 
      switch (reader.Name) 
      { 
       case "Name": 
        var parts = reader.Value.Split(' '); 
        ColonistManager.Population[i].FirstName = parts[0]; 
        ColonistManager.Population[i].NickName = parts[1]; 
        ColonistManager.Population[i].LastName = parts[2]; 
        Log.Message("Colonist Name: " + ColonistManager.Population[i].FirstName + ColonistManager.Population[i].NickName + ColonistManager.Population[i].LastName); 
        break; 

       case "Age": 
        ColonistManager.Population[i].Age = int.Parse(reader.Value); 
        Log.Message("Colonist Age: " + ColonistManager.Population[i].Age.ToString()); 
        break; 
      } 
     } 
    } 

    private static void VisitGraphics(XmlTextReader reader, int i) 
    { 
     while (reader.MoveToNextAttribute()) 
     { 
      switch (reader.Name) 
      { 
       case "BodyType": 
        string body = reader.Value; 
        int bodyType = 0; 
        if (body == "Male") 
        { 
         bodyType = 1; 
        } 
        else if (body == "Female") 
        { 
         bodyType = 2; 
        } 
        else if (body == "Thin") 
        { 
         bodyType = 3; 
        } 
        else if (body == "Hulk") 
        { 
         bodyType = 4; 
        } 
        else if (body == "Fat") 
        { 
         bodyType = 5; 
        } 
        ColonistManager.Population[i].BodyType = (BodyType)bodyType; 
        Log.Message("Colonist BodyType: " + ColonistManager.Population[i].BodyType.ToString()); 
        break; 

       case "SkinColor": 
        ColonistManager.Population[i].SkinColor = GetColor(reader.Value); 
        Log.Message("Colonist SkinColor: " + ColonistManager.Population[i].SkinColor.r.ToString() + ", " + ColonistManager.Population[i].SkinColor.g.ToString() + ", " + ColonistManager.Population[i].SkinColor.b.ToString() + ", " + ColonistManager.Population[i].SkinColor.a.ToString()); 
        break; 

       case "CrownType": 
        string crown = reader.Value; 
        int crownType = 0; 
        if (crown == "Average") 
        { 
         crownType = 1; 
        } 
        else if (crown == "Narrow") 
        { 
         crownType = 2; 
        } 
        ColonistManager.Population[i].CrownType = (CrownType)crownType; 
        break; 

       case "HeadGraphicPath": 
        ColonistManager.Population[i].HeadGraphicPath = reader.Value; 
        break; 

       case "HairColor": 
        ColonistManager.Population[i].HairColor = GetColor(reader.Value); 
        break; 
      } 
     } 
    } 

    private static void VisitHairDef(XmlTextReader reader, int i) 
    { 
     ColHairDef hairDef = new ColHairDef(); 

     while (reader.MoveToNextAttribute()) 
     { 
      switch (reader.Name) 
      { 
       case "DefName": 
        hairDef.DefName = reader.Value; 
        break; 

       case "GraphicPath": 
        hairDef.GraphicPath = reader.Value; 
        break; 

       case "HairGender": 
        string hair = reader.Value; 
        int hairGender = 0; 
        if (hair == "Any") 
        { 
         hairGender = 2; 
        } 
        else if (hair == "Female") 
        { 
         hairGender = 4; 
        } 
        else if (hair == "FemaleUsually") 
        { 
         hairGender = 3; 
        } 
        else if (hair == "MaleUsually") 
        { 
         hairGender = 1; 
        } 
        hairDef.HairGender = (HairGender)hairGender; 
        break; 

       case "Label": 
        hairDef.Label = reader.Value; 
        break; 

       case "Tags": 
        hairDef.HairTags = GetTags(reader.Value); 
        ColonistManager.Population[i].HairDef = hairDef; 
        break; 
      } 
     } 
    } 

    private static List<string> GetTags(string tagList) 
    { 
     List<string> tags = tagList.Split(',').ToList<string>(); 
     return tags; 
    } 

    private static void VisitOnSkin(XmlTextReader reader, int i) 
    { 
     Clothing clothing = new Clothing(); 

     while (reader.MoveToNextAttribute()) 
     { 
      switch (reader.Name) 
      { 
       case "Layer": 
        clothing.Layer = reader.Value; 
        break; 

       case "Label": 
        clothing.Label = reader.Value; 
        break; 

       case "GraphicPath": 
        clothing.GraphicPath = reader.Value; 
        break; 

       case "Color": 
        clothing.Color = GetColor(reader.Value); 
        break; 
      } 
     } 
     ColonistManager.Population[i].Clothing[0] = clothing; 
    } 

    private static void VisitShell(XmlTextReader reader, int i) 
    { 
     Clothing clothing = new Clothing(); 

     while (reader.MoveToNextAttribute()) 
     { 
      switch (reader.Name) 
      { 
       case "Layer": 
        clothing.Layer = reader.Value; 
        break; 

       case "Label": 
        clothing.Label = reader.Value; 
        break; 

       case "GraphicPath": 
        clothing.GraphicPath = reader.Value; 
        break; 

       case "Color": 
        clothing.Color = GetColor(reader.Value); 
        break; 
      } 
     } 
     ColonistManager.Population[i].Clothing[1] = clothing; 
    } 

    private static Color GetColor(string colorValue) 
    { 
     var parts = colorValue.Split(','); 
     Color color = new Color(); 
     color.r = Single.Parse(parts[0]); 
     color.g = Single.Parse(parts[1]); 
     color.b = Single.Parse(parts[2]); 
     color.a = Single.Parse(parts[3]); 

     return color; 
    } 

    private static void VisitChildhood(XmlTextReader reader, int i) 
    { 
     while (reader.MoveToNextAttribute()) 
     { 
      switch (reader.Name) 
      { 
       case "Index": 
        ColonistManager.Population[i].Backstory[0] = ColonistManager.Backstories[int.Parse(reader.Value)]; 
        break; 
      } 
     } 
    } 

    private static void VisitAdulthood(XmlTextReader reader, int i) 
    { 
     while (reader.MoveToNextAttribute()) 
     { 
      switch (reader.Name) 
      { 
       case "Index": 
        ColonistManager.Population[i].Backstory[1] = ColonistManager.Backstories[int.Parse(reader.Value)]; 
        break; 
      } 
     } 
    } 

    private static void VisitSkillPool(XmlTextReader reader, int i) 
    { 
     while (reader.MoveToNextAttribute()) 
     { 
      switch (reader.Name) 
      { 
       case "Amount": 
        ColonistManager.Population[i].SkillPool = int.Parse(reader.Value); 
        break; 
      } 
     } 
    } 

    private static void VisitSkills(XmlTextReader reader, int i) 
    { 
     while (reader.MoveToNextAttribute()) 
     { 
      string name = ""; 
      int value = 0; 
      switch (reader.Name) 
      { 
       case "Name": 
        name = reader.Value; 
        break; 

       case "Value": 
        value = int.Parse(reader.Value); 
        break; 

       case "Passion": 
        value = int.Parse(reader.Value); 
        if (name == "Construction") 
        { 
         ColonistManager.Population[i].Skills[0].SkillName = name; 
         ColonistManager.Population[i].Skills[0].SkillValue = value; 
         ColonistManager.Population[i].Skills[0].SkillPassion = int.Parse(reader.Value); 
        } 
        else if (name == "Growing") 
        { 
         ColonistManager.Population[i].Skills[1].SkillName = name; 
         ColonistManager.Population[i].Skills[1].SkillValue = value; 
         ColonistManager.Population[i].Skills[1].SkillPassion = int.Parse(reader.Value); 
        } 
        else if (name == "Research") 
        { 
         ColonistManager.Population[i].Skills[2].SkillName = name; 
         ColonistManager.Population[i].Skills[2].SkillValue = value; 
         ColonistManager.Population[i].Skills[2].SkillPassion = int.Parse(reader.Value); 
        } 
        else if (name == "Mining") 
        { 
         ColonistManager.Population[i].Skills[3].SkillName = name; 
         ColonistManager.Population[i].Skills[3].SkillValue = value; 
         ColonistManager.Population[i].Skills[3].SkillPassion = int.Parse(reader.Value); 
        } 
        else if (name == "Shooting") 
        { 
         ColonistManager.Population[i].Skills[4].SkillName = name; 
         ColonistManager.Population[i].Skills[4].SkillValue = value; 
         ColonistManager.Population[i].Skills[4].SkillPassion = int.Parse(reader.Value); 
        } 
        else if (name == "Melee") 
        { 
         ColonistManager.Population[i].Skills[5].SkillName = name; 
         ColonistManager.Population[i].Skills[5].SkillValue = value; 
         ColonistManager.Population[i].Skills[5].SkillPassion = int.Parse(reader.Value); 
        } 
        else if (name == "Social") 
        { 
         ColonistManager.Population[i].Skills[6].SkillName = name; 
         ColonistManager.Population[i].Skills[6].SkillValue = value; 
         ColonistManager.Population[i].Skills[6].SkillPassion = int.Parse(reader.Value); 
        } 
        else if (name == "Cooking") 
        { 
         ColonistManager.Population[i].Skills[7].SkillName = name; 
         ColonistManager.Population[i].Skills[7].SkillValue = value; 
         ColonistManager.Population[i].Skills[7].SkillPassion = int.Parse(reader.Value); 
        } 
        else if (name == "Medicine") 
        { 
         ColonistManager.Population[i].Skills[8].SkillName = name; 
         ColonistManager.Population[i].Skills[8].SkillValue = value; 
         ColonistManager.Population[i].Skills[8].SkillPassion = int.Parse(reader.Value); 
        } 
        else if (name == "Artistic") 
        { 
         ColonistManager.Population[i].Skills[9].SkillName = name; 
         ColonistManager.Population[i].Skills[9].SkillValue = value; 
         ColonistManager.Population[i].Skills[9].SkillPassion = int.Parse(reader.Value); 
        } 
        else if (name == "Crafting") 
        { 
         ColonistManager.Population[i].Skills[10].SkillName = name; 
         ColonistManager.Population[i].Skills[10].SkillValue = value; 
         ColonistManager.Population[i].Skills[10].SkillPassion = int.Parse(reader.Value); 
        } 
        break; 
      } 
     } 
    } 
} 

}

下面是XML文件:

<?xml version="1.0" encoding="utf-8"?> 
<Colonists> 
<ColonistAmount amount="1" /> 
<Colonist num="1"> 
    <BasicInfo Name="Argain Don Bentham" /> 
    <BasicInfo Age="29" /> 
    <BasicInfo Gender="1" /> 
    <BasicInfo Trait1="Gadgeteer" /> 
    <BasicInfo Trait2="Knitter" /> 
    <Graphics BodyType="Thin" /> 
    <Graphics SkinColor="0.9490196,0.9294118,0.8784314,1" /> 
    <Graphics CrownType="Narrow" /> 
    <Graphics HeadGraphicPath="Things/Pawn/Humanoid/Heads/Female/Female_Narrow_Wide" /> 
    <Graphics HairColor="0.5,0.5,0.5,1" /> 
    <HairDef DefName="Mop" /> 
    <HairDef GraphicPath="Things/Pawn/Humanoid/Hairs/Mop" /> 
    <HairDef HairGender="MaleUsually" /> 
    <HairDef Label="Mop" /> 
    <HairDef Tags="Urban,Rural" /> 
    <Apparel> 
     <OnSkin Layer="OnSkin" Label="Button-down shirt" GraphicPath="Things/Pawn/Humanoid/Apparel/ShirtButton/ShirtButton" Color="1,1,1,1" /> 
     <Shell Layer="Shell" Label="Duster" GraphicPath="Things/Pawn/Humanoid/Apparel/Duster/Duster" Color="0,0,0,1" /> 
    </Apparel> 
    <Backstories> 
     <Childhood Index="177" /> 
     <Adulthood Index="26" /> 
    </Backstories> 
    <SkillPool Amount="0" /> 
    <Skills Name="Construction" Value="0" Passion="0" /> 
    <Skills Name="Growing" Value="0" Passion="0" /> 
    <Skills Name="Research" Value="6" Passion="0" /> 
    <Skills Name="Mining" Value="0" Passion="0" /> 
    <Skills Name="Shooting" Value="16" Passion="2" /> 
    <Skills Name="Melee" Value="0" Passion="1" /> 
    <Skills Name="Social" Value="18" Passion="3" /> 
    <Skills Name="Cooking" Value="0" Passion="0" /> 
    <Skills Name="Medicine" Value="0" Passion="0" /> 
    <Skills Name="Artistic" Value="0" Passion="0" /> 
    <Skills Name="Crafting" Value="0" Passion="0" /> 
    <End /> 
</Colonist> 
</Colonists> 

我是新使用这种“访客模式”风格,并通过VisitHairDef方法使代码循环出现5次问题。每次此方法循环时,HairDef对象都将被重新创建,随后在将每个循环写入ColonistManager.Population[i].HairDef对象之前,每个循环只存储一条信息。因此,最终结果只有一个变量存储在ColonistManager.Population[i].HairDef中。我不知道为什么这个特定的部分正在循环,并希望有更多的经验的人可以为我提供一些启示。如果需要更多信息,我已将整个源代码上传到Dropbox:https://www.dropbox.com/s/eeq8hwwaoa2ld0b/ColonistCreationMod%20Source.zip

回答

0

使其在Colonist的构造函数中初始化为Colonist.HairDef。然后在VisitHairDef中,直接在ColonistManager.Population[i].HairDef上设置属性。

public class Colonist 
{ 
    public HairDef HairDef { get; set; } 

    public Colonist() 
    { 
     HairDef = new HairDef(); 
    } 
} 


private static void VisitHairDef(XmlTextReader reader, int i) 
{ 
    //ColHairDef hairDef = new ColHairDef(); 

    while (reader.MoveToNextAttribute()) 
    { 
     switch (reader.Name) 
     { 
      case "DefName": 
       ColonistManager.Population[i].HairDef.DefName = reader.Value; 
       break; 

      case "GraphicPath": 
       ColonistManager.Population[i].HairDef.GraphicPath = reader.Value; 
       break; 

      case "HairGender": 
       string hair = reader.Value; 
       int hairGender = 0; 
       if (hair == "Any") 
       { 
        hairGender = 2; 
       } 
       else if (hair == "Female") 
       { 
        hairGender = 4; 
       } 
       else if (hair == "FemaleUsually") 
       { 
        hairGender = 3; 
       } 
       else if (hair == "MaleUsually") 
       { 
        hairGender = 1; 
       } 
       ColonistManager.Population[i].HairDef.HairGender = (HairGender)hairGender; 
       break; 

      case "Label": 
       ColonistManager.Population[i].HairDef.Label = reader.Value; 
       break; 

      case "Tags": 
       ColonistManager.Population[i].HairDef.HairTags = GetTags(reader.Value); 
       //ColonistManager.Population[i].HairDef = hairDef; 
       break; 
     } 
    } 
} 
0

我发现这是用XML文件本身...的VisitOnSkin方法与Clothing clothing = new Clothing();完美无缺的方法中的一个问题,因为XML是像这样:

<OnSkin Layer="OnSkin" Label="Button-down shirt" GraphicPath="Things/Pawn/Humanoid/Apparel/ShirtButton/ShirtButton" Color="1,1,1,1" /> 

为XML的HairDef,然而,是嵌套在一个节点内没有太多的属性......一旦我把所有的下一个“HairDef”节点像这样的属性:

<HairDef DefName="Mop" GraphicPath="Things/Pawn/Humanoid/Hairs/Mop" HairGender="MaleUsually" Label="Mop" Tags="Urban,Rural" /> 

然后一切顺利:D