WCF基于params的自定义序列化

时间:2011-02-15 15:09:07

标签: c# soap wcf

我是否可以实现一些自定义序列化(SOAP)来仅序列化可以动态更改的字段

类别:

[DataContract]
public class Video
{
    ...

    [DataMember]
    public int Width { get; set; }

    [DataMember]
    public int Height { get; set; }

    [DataMember]
    public short Bitrate { get; set; }

    [DataMember]
    public short Framerate { get; set; }

    [DataMember]
    public long Duration { get; set; }

    [DataMember(EmitDefaultValue = false)]
    public VideoType Type { get; set; }
}

WCF方法:

public Video GetPartVideo(params string[] fields)
{
    var video = new Video
    {
        Name = "Test Video",
        Description = "Description of the Test Video",
        CreatedAt = DateTime.Now,
        ModifiedAt = DateTime.Now,
        Url = "",
        FileName = "",
        FileSize = 100,
        Width = 640,
        Height = 480,
        Bitrate = 120,
        Framerate = 32,
        Duration = 100200300,
        Type = VideoType.StandardDefinition
    };

    return video;
} 

方法调用:

<GetPartVideo>
  <MethodParameters>
    <fields attr0="StringArray" isNull="false">
      <StringArray0>Name</StringArray0>
      <StringArray1>Description</StringArray1>
    </fields>
  </MethodParameters>
</GetPartVideo>

SOAP响应(简化):

<GetPartVideo>
  <MethodParameters>
    <Video>
      <Description>Description of the Test Video</Description>
      <Name>Test Video</Name>
    </Video>
  </MethodParameters>
</GetPartVideo>

1 个答案:

答案 0 :(得分:2)

我自己找到了回应。

可以使用Serializer Format Attribute来更改序列化

public class CustomDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior
{
    public CustomDataContractSerializerOperationBehavior(OperationDescription operationDescription) : base(operationDescription) { }

    public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
    {
        var dictionary = new XmlDictionary(2);
        dictionary.Add(name);
        dictionary.Add(ns);


        return new MyCustomDataContractSerializer(
            type,
            new XmlDictionaryString(dictionary, name, 0),
            new XmlDictionaryString(dictionary, ns, 1), 
            knownTypes);
    }

    public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
    {
        return new MyCustomDataContractSerializer(
            type,
            name,
            ns,
            knownTypes);
    }
}


public class CustomDataContractFormatAttribute : Attribute, IOperationBehavior
{
    public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
    {
    }

    public void ApplyClientBehavior(OperationDescription description, ClientOperation proxy)
    {
        ReplaceDataContractSerializerOperationBehavior(description);
    }

    public void ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch)
    {
        ReplaceDataContractSerializerOperationBehavior(description);
    }

    public void Validate(OperationDescription description)
    {
    }

    private static void ReplaceDataContractSerializerOperationBehavior(OperationDescription description)
    {
        DataContractSerializerOperationBehavior dcs = description.Behaviors.Find<DataContractSerializerOperationBehavior>();

        if (dcs != null)
            description.Behaviors.Remove(dcs);

        description.Behaviors.Add(new CustomDataContractSerializerOperationBehavior(description));
    }
}

类MyCustomDataContractSerializer也应覆盖XmlObjectSerializer

和服务可以使用自定义格式属性

进行修饰
[ServiceContract(Namespace = "http://tesmpuri.com/")]
[ServiceKnownType(typeof(Video))]
public interface IPartialResponseTestService
{
    [OperationContract]
    Video GetFullVideo();

    [OperationContract]
    [CustomDataContractFormat]
    Video GetPartVideo(params string[] fields);

    [OperationContract]
    [XmlSerializerFormat]
    Video GetVideo();
}