【问题标题】:Unity 2D - Get value from list of class by class variable's valueUnity 2D - 通过类变量的值从类列表中获取值
【发布时间】:2019-01-09 20:16:01
【问题描述】:

我的 Xml 加载器将数据从 xml 文件保存到类列表。 Dialog 是具有 2 个属性的类:id 和 text,其中保存 xml 文件的内容。我想通过 id 变量的值从 DialogContainer.cs 中的列表中获取 DialogLoader.cs 中的“文本”变量值。我怎样才能做到这一点?这可能很容易,但我不知道如何。

dialogs.xml

<?xml version="1.0" encoding="UTF-8"?>
<DialogCollection>
  <Dialogs>
    <Dialog id="1">
      <Text>Hello my friend</Text>
    </Dialog>
    <Dialog id="2">
      <Text>Hello my grandma</Text>
    </Dialog>
    <Dialog id="3">
      <Text>Hello my grandpa</Text>
    </Dialog>
  </Dialogs>
</DialogCollection>

DialogLoader.cs

public class DialogLoader : MonoBehaviour
{

public const string path = "dialogs";

void Start()
{
    DialogContainer dc = DialogContainer.Load(path);
//There I want to get text for example by id 1 (Hello my friend)
    foreach (Dialog item in dc.dialogs)
    {
        print(item.text);
    }
}

DialogContainer.cs

[XmlRoot("DialogCollection")]
public class DialogContainer
{

    [XmlArray("Dialogs")]
    [XmlArrayItem("Dialog")]
    public List<Dialog> dialogs = new List<Dialog>();

    public static DialogContainer Load(string path)
    {
        TextAsset _xml = Resources.Load<TextAsset>(path);

        XmlSerializer serializer = new XmlSerializer(typeof(DialogContainer));

        StringReader reader = new StringReader(_xml.text);

        DialogContainer dialogs = serializer.Deserialize(reader) as DialogContainer;


        reader.Close();

        return dialogs;
    }


}

Dialog.cs

public class Dialog
{

    [XmlAttribute("id")]
    public string id;

    [XmlElement("Text")]
    public string text;


}

【问题讨论】:

    标签: c# xml list class unity3d


    【解决方案1】:

    您可以添加一个字典,如

    [XmlRoot("DialogCollection")]
    public class DialogContainer
    {
        [XmlArray("Dialogs")]
        [XmlArrayItem("Dialog")]
        public List<Dialog> dialogs = new List<Dialog>();
    
        public Dictionary<string, string> IdToText = new Dictionary<string, string>();
    
        public static DialogContainer Load(string path)
        {
            TextAsset _xml = Resources.Load<TextAsset>(path);
    
            XmlSerializer serializer = new XmlSerializer(typeof(DialogContainer));
    
            // use a better variable name since "dialogs" is also a field of it
            DialogContainer dialogContainer;
    
            // use "using" for disposables
            using(StringReader reader = new StringReader(_xml.text))
            {
                dialogContainer = serializer.Deserialize(reader) as DialogContainer;
            }
    
            // reset dictionary
            dialogContainer.IdToText.Clear();
            foreach(var entry in dialogContainer.dialogs)
            {
                dialogContainer.IdToText.Add(entry.id, entry.text);
            }
    
            return dialogContainer;
        }
    }
    

    比你以后可以使用例如

    aDialogContainer.idTotext["1"];
    

    注意,如果搜索到的键不在字典中,这会抛出异常!所以参考下面的解决方案。


    另一个选项是实现一个 getter 方法而不是字典,以便使用 LINQ: FirstOrDefault 即时查找正确的文本:

    public string IdtoText(string id)
    {
        var foundDialog = dialogs.FirstOrDefault(dialog => string.Equals(dialog.id, id));
    
        //         here you can decide whether to        |
        //         return null or "" if no element found v 
        return foundDialog != null ? foundDialog.text : "";
    }
    

    比你会使用的

    aDialogContainer.IdTotext("1");
    

    【讨论】:

      【解决方案2】:

      您可以使用 Linq 过滤对话框列表并简单地返回第一个符合您条件的对话框。

      类似这样的:

      public Dialog GetSingleDialog(string id, List<Dialog> dialogs){
      
      return dialogs.Where(x=>x.id==id).FirstOrDefault();
      }
      

      你可以这样使用:

      DialogContainer dc = DialogContainer.Load(path);
      //Get list of dialogs
      var dialogs=dc.dialogs;
      var theDialog=GetSingleDialog("1",dialogs);
      

      //获取你的文本

      Debug.Log(theDialog.Text);
      

      【讨论】:

      • 请注意,Where 不会返回单个值,而是返回一个 IEnumerable&lt;Dialog&gt;
      • 请注意,Where 返回一个 IEnumerable&lt;Dialog&gt;不是单个值
      • 不知何故,我觉得我输入了FirstOrDefault(); 感谢您提醒我注意这一点。
      • 在这种情况下.. 为什么Where 的不必要调用.. 您可以在原始列表中直接使用FirstOrDefault。您还必须使用 static 并使用 var theDialog = DialogContainer.GetSingleDialog("1", dialogs); 或使用 var theDialog = dc.GetSingleDialog("1", dialogs); .. 但是在这种情况下,必须先获取 List 引用有点多余...
      猜你喜欢
      • 2021-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-23
      • 2021-01-30
      • 1970-01-01
      相关资源
      最近更新 更多