【问题标题】:Serialization: Dynamic class names序列化:动态类名
【发布时间】:2016-11-02 05:50:10
【问题描述】:

我已经尝试了各种可能性,但也许我只是太厌倦了看到解决方案-.-

我有一个这样的 xml 结构:

<diagnosisList>
  <diagnosis>
    <surgery1>
        <date>1957-08-13</date>
        <description>a</description>
        <ops301>0-000</ops301>
    </surgery1>
    <surgery2>
        <date>1957-08-13</date>
        <description>a</description>
        <ops301>0-000</ops301>
    </surgery2>
    <surgery...>
    </surgery...>
  </diagnosis>
</diagnosisList>

如您所见,手术次数不定。我有一个包含 XML 元素的“手术”类。

class Surgery
    {
        [XmlElement("date")]
        public string date { get; set; }

        [XmlElement("description")]
        public string description { get; set; }

        [XmlElement("ops301")]
        public string ops301 { get; set; }

        public Surgery()
        {
        }
    }

以及通过将手术类添加到构造函数来创建结构的类诊断。

诊断.cs

class Diagnosis
    {
        [XmlElement("surgery")]
        public Surgery surgery
        {
            get;
            set;
        }

        public Diagnosis(Surgery Surgery)
        {
            surgery = Surgery;
        }
    }

我需要能够通过在序列化之前添加一个数字来动态序列化手术的类名。

有人知道实现这一目标的方法吗?

非常感谢任何帮助:)

亲切的问候 桑德罗

-- 编辑

我从我的根类“Import”开始创建整个结构。然后这个类将被传递给序列化器。所以我不能在创建结构的过程中使用 XMLWriter。我需要先创建整个结构,最后将其序列化:

private static void XmlFileSerialization(Import import)
{
  string filename = @"c:\dump\trauma.xml";

  // default file serialization
  XmlSerializer<Import>.SerializeToFile(import, filename);

  XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
  namespaces.Add("", "");

  XmlWriterSettings settings = new XmlWriterSettings();
  settings.Encoding = Encoding.UTF8;
  settings.Indent = true;
  settings.IndentChars = "\t";

  XmlSerializer<Import>.SerializeToFile(import, filename, namespaces, settings);
}

然后在方法“SerializeToFile”中

public static void SerializeToFile(T source, string filename, XmlSerializerNamespaces namespaces, XmlWriterSettings settings)
        {
           if (source == null)
             throw new ArgumentNullException("source", "Object to serialize cannot be null");

           XmlSerializer serializer = new XmlSerializer(source.GetType());
           using (XmlWriter xmlWriter = XmlWriter.Create(filename, settings))
           {
              System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(T));
              x.Serialize(xmlWriter, source, namespaces);
                    }
           }
    }

我需要的是能够基于主类“Surgery”实例化可变数量的类。该类必须有一个变量名称,即

手术1、手术2、手术3等

这不能更改,因为这是由定义 XML 结构的机构给出的。

类必须可以通过其动态名称访问,因为必须设置类中的属性。

所以:

surgery1.Property = "blabla";

手术2。属性 = "babla";

等等

我什至在考虑使用T4的方法来创建这部分代码,但是必须有另一种方法来实现动态类名。

我还想过使用反射创建具有类变量名的实例:

System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(string className)

但这实际上不起作用-.-

有没有人有提示可以让我找到正确的方向?

【问题讨论】:

标签: c# class serialization dynamic


【解决方案1】:

我认为,您可以尝试在包含 diagnosisList 的对象中实现来自 IXmlSerializable 的方法。

【讨论】:

    【解决方案2】:

    尝试使用自定义的 xml 写入器和读取器。

    public class SurgeryWriter : XmlTextWriter
    {
        public SurgeryWriter(string url) : base(url, Encoding.UTF8) { }
    
        private int counter = 1;
    
        public override void WriteStartElement(string prefix, string localName, string ns)
        {
            if (localName == "surgery")
            {
                base.WriteStartElement(prefix, "surgery" + counter, ns);
                counter++;
            }
            else
                base.WriteStartElement(prefix, localName, ns);
        }
    }
    
    public class SurgeryReader : XmlTextReader
    {
        public SurgeryReader(string url) : base(url) { }
    
        public override string LocalName
        {
            get
            {
                if (base.LocalName.StartsWith("surgery"))
                    return "surgery";
                return base.LocalName;
            }
        }
    }
    

    类:

    [XmlRoot("diagnosisList")]
    public class DiagnosisList
    {
        [XmlArray("diagnosis")]
        [XmlArrayItem("surgery")]
        public Surgery[] Diagnosis { get; set; }
    }
    
    [XmlRoot("surgery")]
    public class Surgery
    {
        [XmlElement("date", DataType = "date")]
        public DateTime Date { get; set; }
        [XmlElement("description")]
        public string Description { get; set; }
        [XmlElement("ops301")]
        public string Ops301 { get; set; }
    }
    

    用途:

    var xs = new XmlSerializer(typeof(DiagnosisList));
    DiagnosisList diagnosisList;
    
    using (var reader = new SurgeryReader("test.xml"))
        diagnosisList = (DiagnosisList)xs.Deserialize(reader);
    
    using (var writer = new SurgeryWriter("test2.xml"))
        xs.Serialize(writer, diagnosisList);
    

    不要混合使用 XML 和 C#。

    C# 代码中不需要动态名称!

    如果您需要任意数量的类实例,请在循环中创建它们并将其放置在任何集合中。

    var surgeries = new List<Surgery>();
    
    for (int i = 0; i < 10; i++)
    {
        var surgery = new Surgery();
        surgeries.Add(surgery);
    }
    

    稍后您可以通过索引或枚举来访问它们。

    surgeries[5]
    
    foreach (var surgery in surgeries)
    {
        // use surgery
    }
    

    如您所见,不需要动态名称!


    或者,使用任意名称的字典作为键。

    var surgeryDict = new Dictionary<string, Surgery>();
    
    for (int i = 0; i < 10; i++)
    {
        var surgery = new Surgery();
        surgeryDict["surgery" + i] = surgery;
    }
    

    按名称访问:

    surgeryDict["surgery5"]
    

    【讨论】:

    • 谢谢大家的提示,但不幸的是它直到现在才起作用。作为附加信息:我有这个架构给出的结构,我必须序列化一个不反序列化它:)
    • @SandroColletti - 我的错。一般来说,最好按照 lokusking 的建议使用 id 属性。我会看看我能为你做些什么。
    • @SandroColletti - 查看更新。我添加了自定义 xml 编写器。
    • 非常感谢您的回复 :) 如前所述,我没有机会更改 XML,因为它是作为修复结构提供的,来自我们要为其导出数据的机构。我会看看你的例子:)
    • 我有点迷茫,所以这里有更多详细信息。我从我的根类“Import”开始创建整个结构,它将被传递给序列化程序方法。请参阅我在问题中所做的更新。
    猜你喜欢
    • 2015-03-17
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多