Проблема использования сериализации DataContract Xml - KnownTypes - PullRequest
0 голосов
/ 04 октября 2019

У меня проблема, когда я хочу сериализировать XML с помощью DataContract, у меня возникает исключение ошибки, в котором мне предлагается использовать DataContractResolver или добавить типы UnKnown ...

У меня есть 3 плагина, которые могут быть загружены динамически с помощьюDll: Class1, Class2 и ClassPanel и pluginProperty Class3, который является общим для всех плагинов.

Я создаю различные экземпляры плагинов и сохраняю их в контейнере. Главное окно и панели имеют контейнер

, поэтому я бы сериализовал каждый плагин, включенный в контейнер, в субконтейнер и в субконтейнер ..., а также в каждый макет свойства (Class3).

Так что я не знаю, чтобы добавить различные типы, необходимые для DataContract (динамически). Может быть, невозможно использовать DataContract в этом контексте, и я делаю и пишу пользовательскую программу для сериализации? Спасибо за вашу помощь

//MainWindow.xaml.cs
using System.Runtime.Serialization;
using System.Windows;
using System.Xml;

namespace ClassApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var p = new Plugins();
            var type = p.GetType();
            var dcs = new DataContractSerializer(type);
            using (XmlWriter wr = XmlWriter.Create(@"j:\message.xml"))
            {
                dcs.WriteObject(wr, p);
            }
        }
    }
}

//Plugin.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;

namespace ClassApp1
{
    [DataContract]
    public class Plugins
    {
        [DataMember] public List<object> container = new List<object>();
        public List<Type> pluginTypes;
        public List<Assembly> assemblies = new List<Assembly>();

        public Plugins()
        {
            assemblies.Add(Assembly.LoadFile(System.IO.Path.Combine(@"J:\ProjetC#\Cockpit-master\ClassApp1\bin\Debug", "ClassLibrary3.dll")));
            assemblies.Add(Assembly.LoadFile(System.IO.Path.Combine(@"J:\ProjetC#\Cockpit-master\ClassApp1\bin\Debug", "ClassLibrary1.dll")));
            assemblies.Add(Assembly.LoadFile(System.IO.Path.Combine(@"J:\ProjetC#\Cockpit-master\ClassApp1\bin\Debug", "ClassLibrary2.dll")));
            assemblies.Add(Assembly.LoadFile(System.IO.Path.Combine(@"J:\ProjetC#\Cockpit-master\ClassPanel\bin\Debug", "ClassPanel.dll")));

            pluginTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(a => a.ToString().StartsWith("Class")).ToList();

            var listoftypes = new List<string> { "ClassLibrary1.Class1", "ClassLibrary2.Class2", "ClassPanel.ClassPanel" };
            var listofargs = new List<object> { new object[] { 1, "iamClass1" }, new object[] { 2, 123d }, new object[] { this } };

            for (int i = 0; i < listoftypes.Count(); i++)
            {
                container.Add(Activator.CreateInstance(GetType(listoftypes[i]), listofargs[i]));
            }
        }
        public Type GetType(string model)
        {
            foreach (var p in assemblies)
            {
                Type type = p.GetType(model);
                if (type != null)
                    return type;
            }
            return null;
        }
    }
}

//Class1.cs
using ClassLibrary3;
using System.Runtime.Serialization;

namespace ClassLibrary1
{
    [DataContract]
    public class Class1
    {
        [DataMember] public int id { get; set; }
        [DataMember] public string message { get; set; }
        [DataMember]public Class3 Layout { get; set; }

        public Class1(params object[] obj)
        {
            this.id = (int)obj[0];
            this.message =(string)obj[1];
            Layout = new Class3(id, "fromClass1");
        }
    }
}

//Class2.cs
using ClassLibrary3;
using System.Runtime.Serialization;

namespace ClassLibrary2
{
    [DataContract]
    public class Class2
    {
        [DataMember] public int id { get; set; }
        [DataMember] public double number { get; set; }
        [DataMember] public Class3 Layout { get; set; }

        public Class2(params object[] obj)
        {
            this.id = (int)obj[0];
            this.number = (double)obj[1];
            Layout = new Class3(id, "fromClass2");
        }
    }
}

//Class3.cs
using System.Runtime.Serialization;
using System.Windows.Forms;

namespace ClassLibrary3
{
    [DataContract]
    public class Class3
    {
        public Class3(int id, string name)
        {
            this.id = id;
            this.name = name;
            abc = "ABCDEF";
        }

       [DataMember] public int id { get; set; }
       [DataMember] public string name { get; set; }
       [DataMember] public string abc { get; set; }
    }
}

//ClassPanel.cs
using ClassApp1;
using ClassLibrary3;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;

namespace ClassPanel
{
    [DataContract]
    public class ClassPanel
    {
        [DataMember]public List<object> container = new List<object>();

        [DataMember]public Class3 Layout { get; set; }

        public Plugins plg { get; set; }

        public ClassPanel(params object[] obj)
        {
            plg = (Plugins)obj[0];
            Layout = new Class3(0, "fromPanel");

            var listoftypes = new List<string> { "ClassLibrary1.Class1", "ClassLibrary2.Class2", "ClassLibrary1.Class1" };
            var listofargs = new List<object> { new object[] { 11, "iamClass1Panel" }, new object[] { 12, 11d }, new object[] { 12, "iamClass1BisPanel" } };

            for (int i = 0; i < listoftypes.Count(); i++)
            {
                container.Add(Activator.CreateInstance(plg.GetType(listoftypes[i]), listofargs[i]));
            }
        }
    }
}

1 Ответ

0 голосов
/ 04 октября 2019

Хорошо, с большим количеством тестов, я нашел решение и опубликовал его, чтобы помочь людям, которые ищут: Решение состоит в том, чтобы указать все типы, необходимые для сериализации в массиве, как второй параметр DataContractSerializer

namespace ClassApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var p = new Plugins();

            var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(a => a.ToString().StartsWith("ClassP") || a.ToString().StartsWith("ClassL")).ToArray();

            var type = p.GetType();
            var dcs = new DataContractSerializer(type, types);

            var settings = new XmlWriterSettings()
            {
                Indent = true,
                IndentChars = "    "
            };

            using (XmlWriter wr = XmlWriter.Create(@"j:\message.xml", settings))
            {
                dcs.WriteObject(wr,  p);
            }

        }
    }
}

Результат с настройкой XmlWriter (отступ)

<?xml version="1.0" encoding="utf-8"?>
<Plugins xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ClassApp1">
    <container xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <d2p1:anyType xmlns:d3p1="http://schemas.datacontract.org/2004/07/ClassLibrary1" i:type="d3p1:Class1">
            <d3p1:Layout xmlns:d4p1="http://schemas.datacontract.org/2004/07/ClassLibrary3">
                <d4p1:abc>ABCDEF</d4p1:abc>
                <d4p1:id>1</d4p1:id>
                <d4p1:name>fromClass1</d4p1:name>
            </d3p1:Layout>
            <d3p1:id>1</d3p1:id>
            <d3p1:message>iamClass1</d3p1:message>
        </d2p1:anyType>
        <d2p1:anyType xmlns:d3p1="http://schemas.datacontract.org/2004/07/ClassLibrary2" i:type="d3p1:Class2">
            <d3p1:Layout xmlns:d4p1="http://schemas.datacontract.org/2004/07/ClassLibrary3">
                <d4p1:abc>ABCDEF</d4p1:abc>
                <d4p1:id>2</d4p1:id>
                <d4p1:name>fromClass2</d4p1:name>
            </d3p1:Layout>
            <d3p1:id>2</d3p1:id>
            <d3p1:number>123</d3p1:number>
        </d2p1:anyType>
        <d2p1:anyType xmlns:d3p1="http://schemas.datacontract.org/2004/07/ClassPanel" i:type="d3p1:ClassPanel">
            <d3p1:Layout xmlns:d4p1="http://schemas.datacontract.org/2004/07/ClassLibrary3">
                <d4p1:abc>ABCDEF</d4p1:abc>
                <d4p1:id>0</d4p1:id>
                <d4p1:name>fromPanel</d4p1:name>
            </d3p1:Layout>
            <d3p1:container>
                <d2p1:anyType xmlns:d5p1="http://schemas.datacontract.org/2004/07/ClassLibrary1" i:type="d5p1:Class1">
                    <d5p1:Layout xmlns:d6p1="http://schemas.datacontract.org/2004/07/ClassLibrary3">
                        <d6p1:abc>ABCDEF</d6p1:abc>
                        <d6p1:id>11</d6p1:id>
                        <d6p1:name>fromClass1</d6p1:name>
                    </d5p1:Layout>
                    <d5p1:id>11</d5p1:id>
                    <d5p1:message>iamClass1Panel</d5p1:message>
                </d2p1:anyType>
                <d2p1:anyType xmlns:d5p1="http://schemas.datacontract.org/2004/07/ClassLibrary2" i:type="d5p1:Class2">
                    <d5p1:Layout xmlns:d6p1="http://schemas.datacontract.org/2004/07/ClassLibrary3">
                        <d6p1:abc>ABCDEF</d6p1:abc>
                        <d6p1:id>12</d6p1:id>
                        <d6p1:name>fromClass2</d6p1:name>
                    </d5p1:Layout>
                    <d5p1:id>12</d5p1:id>
                    <d5p1:number>11</d5p1:number>
                </d2p1:anyType>
                <d2p1:anyType xmlns:d5p1="http://schemas.datacontract.org/2004/07/ClassLibrary1" i:type="d5p1:Class1">
                    <d5p1:Layout xmlns:d6p1="http://schemas.datacontract.org/2004/07/ClassLibrary3">
                        <d6p1:abc>ABCDEF</d6p1:abc>
                        <d6p1:id>12</d6p1:id>
                        <d6p1:name>fromClass1</d6p1:name>
                    </d5p1:Layout>
                    <d5p1:id>12</d5p1:id>
                    <d5p1:message>iamClass1BisPanel</d5p1:message>
                </d2p1:anyType>
            </d3p1:container>
        </d2p1:anyType>
    </container>
</Plugins>
...