【问题标题】:Partial serialization with DataContractJsonSerializer使用 DataContractJsonSerializer 进行部分序列化
【发布时间】:2015-03-26 09:28:42
【问题描述】:

我在旧版 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”。但是我想知道是否可以在没有流的情况下序列化对象的其余部分。

我考虑过仅为了序列化而更改对象类型,例如通过将其映射到具有原始对象子集的另一个对象,但这种解决方案并不让我满意,因为我正在检查并交换大量数据一个应该很低调的操作。

【问题讨论】:

    标签: c# wcf serialization


    【解决方案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;
        }
    }
    

    【讨论】:

    • 太好了!但是我遇到了一个奇怪的问题,就是找不到您使用的constructor。好吧,我用了另一个,它可以工作
    • 这是 .Net 4.5 (link) 中的新构造函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多