使用 DataContract 的问题 Xml 序列化 - KnownTypes
Problem to use DataContract Xml Serialization - KnownTypes
当我想 Xml 使用 DataContract 序列化时遇到问题,我有一个错误异常要求我使用 DataContractResolver 或添加未知类型...
我有 3 个可以使用 Dll 动态加载的插件:Class1、Class2 和 ClassPanel 以及一个插件属性 Class3,它对所有插件都是通用的。
我创建了不同的插件实例并将它们存储在容器中。
主 window 和面板有容器
所以我会序列化包含在容器、子容器和子容器中的每个插件...以及每个 属性 布局(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]));
}
}
}
}
好的,经过大量测试,我找到了一个解决方案 post 它可以帮助人们搜索:
解决方案是在一个数组中指明序列化所需的所有类型,作为 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>
当我想 Xml 使用 DataContract 序列化时遇到问题,我有一个错误异常要求我使用 DataContractResolver 或添加未知类型...
我有 3 个可以使用 Dll 动态加载的插件:Class1、Class2 和 ClassPanel 以及一个插件属性 Class3,它对所有插件都是通用的。
我创建了不同的插件实例并将它们存储在容器中。 主 window 和面板有容器
所以我会序列化包含在容器、子容器和子容器中的每个插件...以及每个 属性 布局(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]));
}
}
}
}
好的,经过大量测试,我找到了一个解决方案 post 它可以帮助人们搜索: 解决方案是在一个数组中指明序列化所需的所有类型,作为 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>