KnownType для MessageContract в WCF

Я использую объект Stream внутри своих контрактов wcf, поэтому вынужден использовать 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.

Я пробовал погуглить, но не нашел ничего, связанного с KnownType с MessageContract.

Как было предложено в комментарии ... я обновил свой контракт сообщения с KnownType, но они все еще не доступны клиенту через ссылку на службу ...

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

    public class Document : DocumentInfo, IDisposable
    {
}

Кто-нибудь может мне помочь, что здесь не так?

Примечание: ВСЕ KnownType унаследованы от Document


person Abhash786    schedule 16.07.2016    source источник
comment
Мне кажется неправильным то, что вы говорите. Насколько мне известно, вы можете использовать KnownType на MessageContract. Но я считаю, что помню, потоки не сериализуемы, что означает, что вы не сможете их передавать. Также ознакомьтесь с этим   -  person lokusking    schedule 16.07.2016
comment
Вы можете опубликовать исключение? Кроме того, вы также отметили DocumentInfo как известного типа?   -  person lokusking    schedule 19.07.2016
comment
Нет никаких исключений. Я не могу просто увидеть производные типы в сгенерированном прокси-коде. и информация о документе не упоминается как knownType, поскольку она уже является частью одного из методов в контракте на обслуживание.   -  person Abhash786    schedule 19.07.2016


Ответы (1)


Контракты сообщений описывают именно то, как должно выглядеть сообщение. Они поддерживают наследование, но вы должны указать точный контракт сообщения, который вы используете в конкретной операции.

Если вы проверите части сообщения:

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, поэтому остальные свойства должны быть в заголовках.

person Eli Arbel    schedule 19.07.2016
comment
Спасибо ... это именно то, что мне нужно. - person Abhash786; 19.07.2016