2012-07-03 3 views
1

у меня есть интерфейс и класс, определенный в отдельных сборках, как это:Не удается получить KnownType работать с WCF

namespace DataInterfaces 
{ 
    public interface IPerson 
    { 
     string Name { get; set; } 
    } 
} 

namespace DataObjects 
{ 
    [DataContract] 
    [KnownType(typeof(IPerson)) ] 
    public class Person : IPerson 
    { 
     [DataMember] 
     public string Name { get; set; } 
    } 
} 

Это моя служба Интерфейс:

public interface ICalculator 
{ 
    [OperationContract] 
    IPerson GetPerson (); 
} 

Когда я обновляю моя служба Ссылка для моего клиента, я получаю это в Reference.cs:

public object GetPerson() { 
    return base.Channel.GetPerson(); 

Я надеялся, что KnownType даст мне IPerson вместо " объект "здесь.

Я также пробовал [KnownType(typeof(Person)) ] с тем же результатом. Я контролирую как клиент, так и сервер, поэтому у меня есть данные DataObjects (где Person) и DataInterfaces (где определены IPerson) в обоих местах. Есть ли что-то очевидное, что мне не хватает? Я думал, что KnownType был ответом на возможность использования интерфейсов с WCF.

----- ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ ----- я удалил KnownType из класса Person и добавил

[ServiceKnownType(typeof(Person)) ] 

к моему служебному интерфейсу, как это было предложено Ричардом. Прокси-сервер на стороне клиента по-прежнему выглядит одинаково,

public object GetPerson() { return base.Channel.GetPerson(); 

, но теперь он не взрывается. У клиента просто есть «объект», поэтому он должен передать его в IPerson, прежде чем он станет полезным.

 var person = client.GetPerson (); 
     Console.WriteLine (((IPerson) person).Name); 

ответ

0

Вы должны поместить KnownType на IPerson не на человека, как это:

[KnownType(typeof(Person))] 
public interface IPerson 
{ 
    string Name { get; set; } 
} 
+0

Надеюсь, это не ответ :), потому что это означает, что я не могу иметь отдельные DataObjects и DataInterfaces, потому что это делает круговую ссылку. 'Person: IPerson' против' KnownType Person для IPerson' ... Я думал, что все равно попробую, но я получаю ошибку компиляции, говоря, что KnownType может использоваться только для класса, struct ... –

+0

Да, им нужно будет перейдите в ту же сборку. В качестве альтернативы, если ваша база была классом, а не интерфейсом, вы могли бы предоставить известные типы через статический метод в базовом классе [KnownType (MethodName = ...)].Или вы можете предоставить известные типы непосредственно сериализатору, а не полагаться на него, чтобы обнаружить их через атрибуты или статический метод. –

+0

Я действительно пытаюсь разделить эти сборки, но я ценю альтернативы - хорошее питание для размышлений. –

1

Если вам нужно [ServiceKnownType] по договору оказания услуг, то сборка IPerson не требует знания сборки Person ,

[ServiceKnownType(typeof(Person))] 
public interface ICalculator 
{ 
    [OperationContract] 
    IPerson GetPerson (); 
} 

В качестве альтернативы вы можете использовать версию KnownType constructor that takes a method name. Тогда это могло бы найти известные типы из, скажем, конфигурационного файла

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

+0

Прошу прощения, я не понимаю вашего первого заявления, я проверю его. Что касается вашего вопроса о том, как помогают интерфейсы, у меня есть уровень доступа к данным, который раньше был SubSonic, теперь это EntityFramework. В ожидании такого изменения мы отвлекли слой доступа к данным, так что все, что он доставляет, - это типы интерфейса. (Это необычно?) Поэтому, когда служба работает с объектом данных, он имеет тип интерфейса, а не конкретный. Я думал, что понял, что, поскольку для сериализации требуется конкретный подход, KnownType был обходным путем. –

+0

Я добавил '[ServiceKnownType (typeof (IPerson))]' над моим ServiceContract, и теперь я вижу 'public DataObjects.Person GetPerson() ...' в моей reference.cs. Так лучше. Могу ли я заставить его быть там? –

+0

Согласитесь с замечанием Ричарда относительно интерфейсов. Как правило, концепция плохо отображает мир передачи сообщений XML-сервисов, на которых основан WCF. WSDL, XSD и XML не имеют эквивалентной концепции. Как только вы начнете использовать эти атрибуты KnownType, вы вполне можете исключить возможность взаимодействия этих веб-сервисов с платформами .Net. –

0

Вся идея наследования заключается в том, что базовый класс не знает специализированных классов. Оформление базового класса контракта с данными (обычно определяется в общей DLL) со специализированными типами, как представляется, нарушает основные принципы OOD? IMHO SvcUtil должен выполнять эту работу для вас и использовать известные типы при генерации прокси. Кажется, что базовое ОО даже не рассматривалось, когда был разработан svcutil.

Смежные вопросы