我试图找出保存(序列化)和以后打开(反序列化)树结构的最佳方法.我的结构由具有不同属性的各种对象类型组成,但每个都继承自基本抽象"Node"类.
每个节点都有唯一的ID(GUID),并有一个AddSuperNode(Node nd)方法,用于设置节点的父节点.这反过来调用其他方法,允许父节点知道它具有哪些子节点.但是,某些节点还使用AddAuxSuperNode()方法向节点添加辅助父节点.
我正在使用二进制序列化,但现在我想我想使用一些我有更多控制的东西,并且序列化数据更容易访问.我还希望在反序列化时保留Type信息,并能够序列化私有值.所以DataContractSerializer似乎是最好的方式.
我不能只序列化的根节点直接因为有多个父节点.我不想创建重复的对象.所以我似乎需要将树解构为一个平面列表,然后将其序列化.然后在序列化该列表后重建树.这听起来不错吗?
就像我之前说的,每个节点都有一个唯一的GUID标识符,但是现在节点直接引用它们的父节点/子节点而不存储它们的id.我可以更新AddSuperNode()和AddAuxSuperNode()方法,以便除了直接引用之外还更新要序列化的父ID列表.但是我宁愿只在序列化对象时更新/创建这个列表.所以我想在节点中创建一个UpdateSuperNodeIDRefs()方法,该方法将在序列化之前调用.
以下是我计划对此结构进行序列化和反序列化的操作.任何人都可以建议更好/更清洁/更有效的方法吗?
序列化
1)提供树结构的根节点
2)细分树结构成扁平字典(GUID ID,节点ND)其中ID是GUID的ND.
3)调用UpdateSuperNodeIDRefs() ; 为每个节点更新为其父节点保存的ID.
4)使用DataContractSerializer序列化节点字典
反序列化
1)反序列化节点字典
2)遍历字典中的每个节点,将每个节点重新连接到其父节点.对于存储的任何父ID,查找具有匹配ID 的字典中的相应节点调用AddSuperNode()或AddAuxSuperNode()以将节点重新连接到其父节点.
3)从Dictionary中的任何节点找到结构的根
4)返回根节点
我有一个简单的echo服务,我已经为请求/响应定义了一个操作方法和一对类型:
[ServiceContract(Name = "EchoService",
Namespace = "http://example.com/services",
SessionMode = SessionMode.NotAllowed)]
public interface IEchoService
{
[OperationContract(IsOneWay = false,
Action = "http://example.com/services/EchoService/Echo",
ReplyAction = "http://example.com/services/EchoService/EchoResponse")]
EchoResponse Echo(EchoRequest value);
}
Run Code Online (Sandbox Code Playgroud)
数据类型:
[Serializable]
[DataContract(Namespace = "http://example.com/services/EchoService",
Name = "EchoRequest")]
public class EchoRequest
{
public EchoRequest() { }
public EchoRequest(String value)
{
Value = value;
}
[DataMember]
public String Value { get; set; }
}
[Serializable]
[DataContract(Namespace = "http://example.com/services/EchoService",
Name = "EchoResponse")]
public class EchoResponse
{
public EchoResponse() { }
public EchoResponse(String value)
{
Value …Run Code Online (Sandbox Code Playgroud) 我已经看了一会儿了
似乎不鼓励使用二进制序列化,因为对字段名称的任何更改都会破坏序列化=?不好
XMLSerializer是有问题的,因为您必须提供无参数构造函数和公共字段,尽管您可以更多地控制元素属性或元素及其命名
DataContractSerializer很好,但需要明确添加所有的分类,这是一种耻辱
但是我偶然发现NetDataContractSerializer没有这个限制.
如果你的目标是C#序列化并且对xml的大小没有很大的限制,那么NetDataContractSerializer总是可以去这里吗?
在我们的生产环境中,我们的WCF服务使用XMLSerializer进行序列化.为此,我们的服务接口具有[XMLSerializerFormat]属性.现在,我们需要更改为DataContractSerializer,但我们必须与现有客户端保持兼容.因此,我们必须使用两个序列化程序公开每个服务.
我们有一个约束:我们不想重新定义每个合同接口两次,我们有50个服务合同接口,我们不希望有
IIncidentServiceXml
IIncidentServiceDCS
IEmployeeServiceXml
IEmployeeServiceDCS
IContractServiceXml
IContractServiceDCS
Run Code Online (Sandbox Code Playgroud)
我们怎么做?
更多信息
这是对我们迄今为止所尝试的内容的描述,但我愿意尝试完全不同的方法:
我们尝试通过自己的ServiceHostFactory类中的代码创建所有端点.基本上我们创建两个端点两次.问题是在运行时,WCF抱怨该服务有两个具有相同联系人名称但具有不同ContractDescription实例的端点.消息说我们应该使用不同的合同名称或重用相同的ContractDescription实例.
其他尝试:
我们还尝试通过为每个ContractDescription实例使用不同的命名空间来实现.这样我们将保持相同的合同接口(IIncidentService),但有两个不同的命名空间:
http://ourcompany/XML/IIncidentService
http://ourcompany/DCS/IIncidentService
Run Code Online (Sandbox Code Playgroud)
有了这个,我们能够得到更远,但服务崩溃与一个奇怪的例外:
An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
System.InvalidOperationException: An exception was thrown in a call to a WSDL export extension: System.ServiceModel.Description.XmlSerializerOperationBehavior
contract: http://ourcompany.cs/XML:IUserServiceWCF ----> System.NullReferenceException: Object reference not set to an instance of an object.
at System.ServiceModel.Description.XmlSerializerMessageContractExporter.ExportFaults(Object state)
at System.ServiceModel.Description.MessageContractExporter.ExportMessageContract()
at System.ServiceModel.Description.XmlSerializerOperationBehavior.System.ServiceModel.Description.IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext contractContext)
at System.ServiceModel.Description.WsdlExporter.CallExtension(WsdlContractConversionContext contractContext, IWsdlExportExtension extension)
Run Code Online (Sandbox Code Playgroud) 我想将datacontract类序列化为XMl,但没有命名空间.
我已经添加:
[DataContract(Namespace="")]
Run Code Online (Sandbox Code Playgroud)
但我仍然得到:
<Person xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Title>Mr</Title>
...
</Person>
Run Code Online (Sandbox Code Playgroud)
有没有办法阻止这种情况发生,因为我只想将干净的xml传递给遗留组件.
我正在阅读文章,以了解有关datacontractserializer和binaryformatter序列化器的更多信息.基于到目前为止所做的阅读,我的印象是binaryformatter应该比datacontractserializer的占用空间小.原因是DataContractSerializer序列化为xml信息集,而binaryformatter序列化为专有二进制格式.
以下是测试
[Serializable]
[DataContract]
public class Packet
{
[DataMember]
public DataSet Data { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Description { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
DataSet填充了表中的121317行[AdventureWorks].[Sales].[SalesOrderDetail]
using (var fs = new FileStream("test1.txt", FileMode.Create))
{
var dcs = new DataContractSerializer(typeof(Packet));
dcs.WriteObject(fs, packet);
Console.WriteLine("Total bytes with dcs = " + fs.Length);
}
using(var fs = new FileStream("test2.txt", FileMode.Create))
{
var bf = new BinaryFormatter();
bf.Serialize(fs, packet);
Console.WriteLine("Total bytes with binaryformatter = …Run Code Online (Sandbox Code Playgroud) DataContractSerializer如果有异常,我正在使用序列化EF4对象到xml.在我的调试日志中,我可以看到当出现问题时想要的是数据内容.
我有两个版本的代码:一个版本序列化为一个文件,一个版本序列化为一个字符串使用StringWriter.
将大项目序列化到文件时,我获得大约16kb的有效xml.当序列化相同的项目到字符串时,xml在12kb之后被截断.知道导致截断的原因吗?
...
var entity = ....
SaveAsXml(entity, @"c:\temp\EntityContent.xml"); // ok size about 16100 btes
var xmlString = GetAsXml(entity); // not ok, size about 12200 bytes
// to make shure that it is not Debug.Writeline that causes the truncation
// start writing near the end of the string
// only 52 bytes are written although the file is 16101 bytes long
System.Diagnostics.Debug.Writeline(xml.Substring(12200));
Run Code Online (Sandbox Code Playgroud)
我的字符串被截断的任何想法?
这是序列化到文件的代码,可以正常工作
public static void SaveAsXml(object objectToSave, string filenameWithPath)
{
string directory = Path.GetDirectoryName(filenameWithPath); …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用DataContractJsonSerializer类将对象列表输出为json格式,但是我一直遇到以下错误.
Type 'Castle.Proxies.JokeCategoryProxy' with data contract name
'JokeCategoryProxy:http://schemas.datacontract.org/2004/07/Castle.Proxies'
is not expected. Consider using a DataContractResolver or add any types not
known statically to the list of known types - for example, by using the
KnownTypeAttribute attribute or by adding them to the list of known
types passed to DataContractSerializer.
Run Code Online (Sandbox Code Playgroud)
我知道这已经得到了回答,但只有在我的对象中有一个属性是另一个自定义对象时才会发生.
[DataContract]
[KnownType(typeof(ModelBase<int>))]
public class Joke : ModelBase<int>
{
[DataMember]
public virtual string JokeText { get; set; }
[DataMember]
public virtual JokeCategory JokeCategory { get; set; }
}
[DataContract]
[KnownType(typeof(ModelBase<int>))]
public …Run Code Online (Sandbox Code Playgroud) .net c# fluent-nhibernate datacontractserializer known-types
在大会A中:
[DataContract]
public class Base
{
[DataMember]
public string SomeText { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在大会B中:
internal class Helper
{
internal static Base Deserialize(string serializedInstanceOfTypeBase)
{
DataContractSerializer serializer = new DataContractSerializer(typeof (Base));
XmlReader reader = XmlReader.Create(new StringReader(serializedInstanceOfTypeBase));
return (Base)serializer.ReadObject(reader);
}
}
Run Code Online (Sandbox Code Playgroud)
在程序集C中:
[DataContract]
public class Derived : Base
{
[DataMember]
public string SomeMoreText { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果我序列化一个类型的实例Derived并将其传递给Helper.Deserialize()方法,它将失败SerializationException:
第1行位置错误2.期望命名空间'http://schemas.datacontract.org/2004/07'中的元素'Base'.遇到名为'Derived'的'Element',命名空间'http://schemas.datacontract .ORG/2004/07' .
我该怎样摆脱这个问题?
我知道KnownType属性,但在程序集A和B编码时,我完全不知道它的派生类型.所以我不能使用那个解决方案.
我的产品设计比较复杂,我不能完全在这里发布.Helper.Desrialize()方法只是得到一个string参数.Base即使在运行时,也无法(至少目前)对程序集A或B了解类的派生类型.
程序集B引用程序集A.但A&B不能引用程序集C. …
我有一个可观察的集合,我正在尝试序列化到磁盘.收到的错误是:
Type 'VisuallySpeaking.Data.GrammarList' with data contract name
'GrammarList:http://schemas.datacontract.org/2004/07/VisuallySpeaking.Data'
is not expected. Consider using a DataContractResolver or add any
types not known statically to the list of known types - for example,
by using the KnownTypeAttribute attribute or by adding them to the
list of known types passed to
DataContractSerializer."} System.Exception
{System.Runtime.Serialization.SerializationException}
Run Code Online (Sandbox Code Playgroud)
这是我的数据对象:
namespace VisuallySpeaking.Data
{
[CollectionDataContract]
public class GrammarList : ObservableCollection<GrammarDataObject>
{
public GrammarList() : base()
{
Add(new GrammarDataObject("My Name", "My name is","Assets/SampleAssets/MyName.png"));
Add(new GrammarDataObject("Where is", "Where is",""));
Add(new GrammarDataObject("Dog", …Run Code Online (Sandbox Code Playgroud) c# wcf observablecollection datacontractserializer windows-store-apps