3

最初の質問

クラスのXmlTypeを動的serializeList<IXmlSerializable>変更したい(属性タグを使用してそれを行うことはできません)IXmlSerializable

XmlAttributeOverridesを使用してそれを実行しようとしましたが、これまでのところ成功していません。

この問題を示すサンプル コードを次に示します。
IXmlSerializable クラス ( MSDNから) :

public class Person : IXmlSerializable
{
    // Private state
    private string personName;


    // Constructors
    public Person(string name)
    {
        personName = name;
    }

    public Person()
    {
        personName = null;
    }


    // Xml Serialization Infrastructure
    public void WriteXml(XmlWriter writer)
    {
        writer.WriteString(personName);
    }

    public void ReadXml(XmlReader reader)
    {
        personName = reader.ReadString();
    }

    public XmlSchema GetSchema()
    {
        return (null);
    }


    // Print
    public override string ToString()
    {
        return (personName);
    }
}

テストクラス (出力にコンソールを使用):

class Program
{
    static void Main(string[] args)
    {
        List<Person> lPersonList = new List<Person> {
            new Person("First"),
            new Person("Second"),
            new Person("Third")
        };
        XmlAttributeOverrides lOverrides = new XmlAttributeOverrides();
        XmlAttributes lAttributes = new XmlAttributes { XmlType = new XmlTypeAttribute("Employee") };
        lOverrides.Add(typeof(Person), lAttributes);

        XmlSerializer lSerialiser = new XmlSerializer(typeof(List<Person>), lOverrides, null, new XmlRootAttribute("Employees"), null);
        XmlSerializerNamespaces lNamespaces = new XmlSerializerNamespaces();
        lNamespaces.Add("", "");
        lSerialiser.Serialize(Console.Out, lPersonList, lNamespaces);

        System.Console.WriteLine("Enter any key to close.");
        System.Console.ReadKey();
    }
}

これが私が取得したいものです:

<Employees>
<Employee>First</Employee>
<Employee>Second</Employee>
<Employee>Third</Employee>
</Employees>

しかし、実行時にこのエラーが発生します:

System.InvalidOperationException: タイプ Person には XmlRoot 属性のみを指定できます。XmlSchemaProviderAttribute を使用してスキーマ タイプを指定してください。

私のPerson クラスが を実装していない場合IXmlSerializable、すべてがうまく機能します...

誰かが私を助けてくれますか?


選択したソリューション ( @dbc answerに基づく)

@dbcが指摘したように、「サロゲート」クラスを使用することは、私が望むことを行う最も簡単な方法です。しかし、既に述べたように、Person 型を動的に変更する必要があるため、属性タグを使用できません。
だから私はまだXmlAttributeOverrides私の最終的なデザインで使用しています、ここにあります:

サロゲートList<Person>クラス(属性タグなしの @dbc と同じ) :

public class EmployeesListSurrogate
{
    public List<Person> EmployeeList { get; set; }

    public static implicit operator List<Person>(EmployeesListSurrogate surrogate)
    {
        return surrogate == null ? null : surrogate.EmployeeList;
    }

    public static implicit operator EmployeesListSurrogate(List<Person> employees)
    {
        return new EmployeesListSurrogate { EmployeeList = employees };
    }
}

surrogate を使用してクラスをテストします。

class Program
{
    static void Main(string[] args)
    {
        List<Person> lPersonList = new List<Person> {
            new Person("First"),
            new Person("Second"),
            new Person("Third")
        };

        XmlAttributeOverrides lOverrides = new XmlAttributeOverrides();
        XmlAttributes lEmployeesListAttributes = new XmlAttributes { XmlRoot = new XmlRootAttribute("Employees") };
        lOverrides.Add(typeof(EmployeesListSurrogate), lEmployeesListAttributes);
        XmlAttributes lEmployeeAttributes = new XmlAttributes { XmlElements = { new XmlElementAttribute("Employee") } };
        lOverrides.Add(typeof(EmployeesListSurrogate), "EmployeeList", lEmployeeAttributes);

        XmlSerializer lSerializer = new XmlSerializer(typeof(EmployeesListSurrogate), lOverrides);
        XmlSerializerNamespaces lNamespaces = new XmlSerializerNamespaces();
        lNamespaces.Add("", "");
        lSerializer.Serialize(Console.Out, (EmployeesListSurrogate)lPersonList, lNamespaces);
    }
}

@dbc に大いに感謝してこれを締めくくりたいと思います。あなたの答えは非常に役に立ち、有益でした。多くのことを学びました。私はあなたに賛成票を投じることはできませんが、コミュニティがそうしてくれることを願っています!

4

1 に答える 1