WCF中MessageContract的KnownType

时间:2016-07-16 16:41:24

标签: wcf c#-4.0 datacontract messagecontract known-types

我在wcf合同中使用Stream对象,因此被迫使用MessageContract代替DataContract

 [MessageContract]
    public class Document 
    {
        [MessageBodyMember(Order = 1)]
        public System.IO.Stream FileData;

}

 [MessageContract]
    public class A : Document 
    {
        [MessageBodyMember]
        public string input;

}

 [MessageContract]
    public class B : Document 
    {
        [MessageBodyMember]
        public string someProp;

}

[ServiceContract]
    public interface ISomeService
    {

        [OperationContract]
        Document SomeMethod(Document file);
}

我希望此服务的使用者创建A或B的对象并使用它来调用服务。在服务方面,我可以将其转换为适当的对象,然后执行一些操作。

问题是我无法使用KnownType指定MessageContract,并且继承合同在用于服务或使用KnownType声明之前无法向客户公开。

我试过google但却找不到与KnownType MessageContract相关的任何内容。

正如评论中所建议的......我更新了与KnownType的留言合同,但他们仍未通过服务参考向客户展示...

[MessageContract]
    [KnownType(typeof(FileSystemStoredDocument))]
    [KnownType(typeof(FileBoundStoredDocument))]
    [KnownType(typeof(SharepointStoredDocument))]

    public class Document : DocumentInfo, IDisposable
    {
}

任何人都可以帮我解决这里的错误吗?

注意:所有KnownType都是继承自Document

1 个答案:

答案 0 :(得分:4)

消息合同描述消息应该是什么样子。它们确实支持继承,但您必须指定您在特定操作中使用的确切消息合同。

如果您检查邮件的正文部分:

ContractDescription.GetContract(typeof(ISomeService)).Operations[0].Messages[0].Body.Parts

您只会看到一个部分 - Stream个对象。这与数据合同形成对比,其中正文包含Object类型的一部分。所以你明白为什么 KnownType不会在这里工作

ContractDescription类用于生成WSDL。请参阅WsdlExporter类。)

可以做的是创建一个包含在邮件合同中的数据合同层次结构,例如

[MessageContract]
public class Document 
{
    [MessageHeader]
    public DocumentProperties Properties;

    [MessageBodyMember(Order = 1)]
    public System.IO.Stream FileData;
}

[DataContract]
[KnownType(typeof(A))]
[KnownType(typeof(B))]
public abstract class DocumentProperties { }

[DataContract]
public class A : DocumentProperties 
{
    [DataMember]
    public string input;
}

[DataContract]
public class B : DocumentProperties 
{
    [DataMember]
    public string someProp;
}

请注意,如果要传递Stream,则不能拥有多个正文成员,因此其余属性必须位于标题中。