您好我有服务合同,并且在其实现中我试图在文本文件中编写它接收的请求参数。这里将'TypeA a'的复合对象作为参数传递。
namespace WebService
{
// NOTE: If you change the interface name "IRequestStatusChanged" here, you must also update the reference to "IRequestStatusChanged" in App.config.
[ServiceContract]
public interface IRequestStatusChanged
{
[OperationContract]
Input StatusChanged(Input In);
}
[Serializable] [DataContract]
public class Input
{
[DataMember]
RequestStatus RS = new RequestStatus();
}
[Serializable] [DataContract]
public class RequestStatus
{
[DataMember]
RequestToken RT = new RequestToken();
[DataMember]
public String State
}
[Serializable] [DataContract]
public class RequestToken
{
[DataMember]
public string Id;
}
}
Implementation of contract
namespace WebService
{
// NOTE: If you change the class name "RequestStatusChanged" here, you must also update the reference to "RequestStatusChanged" in App.config.
public class RequestStatusChanged : IRequestStatusChanged
{
public Input StatusChanged(Input In)
{
/* IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
Stream outfile = new FileStream(@"C:\test.txt", FileMode.Open,FileAccess.Write);
formatter.Serialize(outfile, In);
outfile.Close(); */
XmlSerializer serializer = new XmlSerializer(typeof(Input));
TextWriter TW = new StreamWriter(@"c:\test.xml");
serializer.Serialize(TW, In);
TW.Close();
return In;
}
}
}
之前我尝试使用IFORMATTER序列化对象并将其写入文本文件,但它不是人类可读的,所以我尝试了xml序列化。
当我检查写入的XML文件时,它只有“TypeA”对象的标签,并且不会将“TypeB”和“TypeC”对象写入文件。我已将所有类标记为服务合同中的[Serializable]。我想将以文本或xml格式接收的所有参数写入文件,以便它们可读(日志文件的种类)。
答案 0 :(得分:2)
类型'TypeB'和'TypeC'没有写入文件,因为它们不是必需的 - 当序列化程序序列化或反序列化TypeA的实例时,它知道成员'b'的类型是TypeB
,因此它不会写入类型信息。你还需要这些信息吗?由于您要序列化TypeA
,并且您知道字段b
的类型为TypeB
,因此您不需要日志文件中的额外信息。
在WCF使用的所有序列化程序中,唯一可以“强制”写入类型的是JSON序列化程序 - 但是你会得到结果为JSON,而不是XML - 见下文。
public class StackOverflow_6666697
{
[DataContract]
public class TypeA { [DataMember] public TypeB b = new TypeB(); }
[DataContract]
public class TypeB { [DataMember] public TypeC c = new TypeC(); }
[DataContract]
public class TypeC { [DataMember] public string S1; }
public static void Test()
{
MemoryStream ms = new MemoryStream();
XmlWriterSettings ws = new XmlWriterSettings
{
Indent = true,
IndentChars = " ",
OmitXmlDeclaration = true,
Encoding = Encoding.UTF8
};
TypeA instance = new TypeA { b = new TypeB { c = new TypeC { S1 = "Hello world" } } };
XmlWriter w = XmlWriter.Create(ms, ws);
new XmlSerializer(typeof(TypeA)).Serialize(w, instance);
w.Flush();
Console.WriteLine("XmlSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
w = XmlWriter.Create(ms, ws);
new DataContractSerializer(typeof(TypeA)).WriteObject(w, instance);
w.Flush();
Console.WriteLine("DataContractSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
w = XmlWriter.Create(ms, ws);
new NetDataContractSerializer().WriteObject(w, instance);
w.Flush();
Console.WriteLine("NetDataContractSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
w = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.UTF8);
new DataContractJsonSerializer(typeof(TypeA), null, 65536, false, null, true).WriteObject(w, instance);
w.Flush();
Console.WriteLine("DataContractJsonSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}
}
另一个选项(我真的不建议,因为你为了记录而改变系统的逻辑)是将字段声明为object
。这样,由于声明的类型与实际类型不同,因此将写出类型信息 - 见下文。
public class StackOverflow_6666697
{
[DataContract]
public class TypeA { [DataMember] public object b = new TypeB(); }
[DataContract]
public class TypeB { [DataMember] public object c = new TypeC(); }
[DataContract]
public class TypeC { [DataMember] public string S1; }
public static void Test()
{
MemoryStream ms = new MemoryStream();
XmlWriterSettings ws = new XmlWriterSettings
{
Indent = true,
IndentChars = " ",
OmitXmlDeclaration = true,
Encoding = Encoding.UTF8
};
TypeA instance = new TypeA { b = new TypeB { c = new TypeC { S1 = "Hello world" } } };
XmlWriter w = XmlWriter.Create(ms, ws);
new XmlSerializer(typeof(TypeA), new Type[] { typeof(TypeB), typeof(TypeC) }).Serialize(w, instance);
w.Flush();
Console.WriteLine("XmlSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
w = XmlWriter.Create(ms, ws);
new DataContractSerializer(typeof(TypeA), new Type[] { typeof(TypeB), typeof(TypeC) }).WriteObject(w, instance);
w.Flush();
Console.WriteLine("DataContractSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
w = XmlWriter.Create(ms, ws);
new NetDataContractSerializer().WriteObject(w, instance);
w.Flush();
Console.WriteLine("NetDataContractSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
w = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.UTF8);
new DataContractJsonSerializer(typeof(TypeA), new Type[] { typeof(TypeB), typeof(TypeC) }, 65536, false, null, true).WriteObject(w, instance);
w.Flush();
Console.WriteLine("DataContractJsonSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}
}
答案 1 :(得分:0)
XmlSerializer
仅序列化公共成员。您定义的DataContract
类型中的所有成员都没有任何访问说明符,因此它们默认为私有。
但是,您在这里使用了两个不同的序列化框架 - 除非您另有说明,否则WCF会隐式使用DataContractSerializer
和XmlSerializer
。为什么不使用DataContractSerializer
,因为您已经拥有了WCF所需的所有属性?
var serialiser = new DataContractSerializer(typeof(TypeA));
serialiser.WriteObject(xmlWriter, typeAObj);