我在旧版WCF服务中使用了以下类
[MessageContract()]
public class Document
{
[MessageHeader(MustUnderstand = true)]
public MetaData Data { get; set; }
[MessageHeader(MustUnderstand = true)]
public string Name { get; set; }
[MessageBodyMember(Order = 1)]
public Stream File { get; set; }
}
这是一个名为AddDocument
的方法,用于将文档推送到商店。
在过去的某个时刻,我通过Castle.Windsor拦截器添加了对我们所有服务的日志记录,这些拦截器序列化了传递的数据,以便跟踪传递给服务的内容。
public void Intercept(IInvocation invocation)
{
Logger.Debug(() =>
{
StringBuilder sb = new StringBuilder(1000);
sb.AppendFormat("{2} -> {0}.{1}(", invocation.TargetType.Name, invocation.Method.Name, SomeCode);
sb.Append(string.Join(", ", invocation.Arguments.Select(a => a == null ? "null" : DumpObject(a)).ToArray()));
sb.Append(")");
return sb.ToString();
});
invocation.Proceed();
Logger.Debug(() =>
{
StringBuilder sb = new StringBuilder(1000);
sb.AppendFormat("OUT {0}", invocation.ReturnValue != null ? DumpObject(invocation.ReturnValue) : "void");
return sb.ToString();
});
}
使用DumpObject
DataContractJsonSerializer
中进行序列化
private string DumpObject(object argument)
{
using (var ms = new MemoryStream())
{
try
{
var ser = new System.Runtime.Serialization.Json.DataContractJsonSerializer(argument.GetType());
ser.WriteObject(ms, argument);
return System.Text.Encoding.UTF8.GetString(ms.GetBuffer(), 0, Convert.ToInt32(ms.Length));
}
catch (Exception)
{
return "NA";
}
}
}
我无法序列化Document
类,因为它包含Stream
,并且参数始终被序列化为' NA'。但是,我想知道是否可以在没有流的情况下序列化对象的其余部分。
我考虑过更改对象类型只是为了序列化,例如通过将其映射到具有原始对象子集的另一个对象,但是这个解决方案并不让我满意,因为我正在检查和交换一个应该是非常低调的操作的大量数据。
答案 0 :(得分:1)
这可以通过实施IDataContactSurrogate
并将其提供给DataContractJsonSerializer
来完成。
var settings = new DataContractJsonSerializerSettings() { DataContractSurrogate = new SkipStreamSurrogate()};
var serializer = new DataContractJsonSerializer(argument.GetType(), settings);
serializer.WriteObject(ms, argument);
实现:
public sealed class SkipStreamSurrogate : IDataContractSurrogate
{
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
return null;
}
public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)
{
return null;
}
public Type GetDataContractType(Type type)
{
return type;
}
public object GetDeserializedObject(object obj, Type targetType)
{
return obj;
}
public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
{
}
public object GetObjectToSerialize(object obj, Type targetType)
{
// Skip serialization of a System.Stream
if (obj is Stream)
{ return null; }
return obj;
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
return null;
}
public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit)
{
return typeDeclaration;
}
}