WCF возвращает объекты клиенту - PullRequest
7 голосов
/ 06 ноября 2010

Я пытаюсь поиграть с WCF и думаю, что попал в блок. Моя проблема в том, что я могу звонить Add(double,double) и getPerson() с «Клиента». Однако я не могу вызвать какие-либо методы объекта Person. Я раздели классы голыми методами. Вот мои фрагменты кода, пожалуйста, дайте мне знать, что я делаю неправильно ..

Server Code

  namespace Test.WebSvc{
  [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Sample")]
  public interface ICalculator
  {
    [OperationContract]
    double Add(double n1, double n2);
    [OperationContract]
    Person getPerson();
  }


 public class CalculatorService : ICalculator
 {
    public double Add(double n1, double n2) { return n1+n2 ; }
    public Person getPerson(){ 
    Person tempPerson = new Person();
    return tempPerson; 
    }
 }

 [DataContract]
 public class Person{
 [OperationContractAttribute]
 public string toString(){
 return "This is a Person Object";
 }

Client Code

ServiceRef1.CalculatorClient client = ServiceRef1.CalculatorClient();//works
Console.WriteLine(client.Add(1.0,2.0)); //this too works   
ServiceRef1.Person p = client.getPerson(); // this is OK., but is not doing what I wanted it to do
Console.WriteLine(p.toString()); // I do not get "This is Person Object"

Я предполагаю, что что-то не так с объявлением моего класса Person ... но не понимаю, что мне делать или чего мне не хватает ..

Спасибо!

Ответы [ 2 ]

11 голосов
/ 06 ноября 2010

Да, вы преодолели барьер - WCF - это система, основанная на сообщениях, которая обменивается только сериализованными данными в формате XML или JSON в текстовом или двоичном формате.Он не однако передает "полные" .NET-объекты с их полными возможностями, такими как методы и все такое (как это должно быть? Он спроектирован так, чтобы быть совместимым , и я непосмотрите, как клиент Ruby или PHP может вызывать метод объекта .NET.

WCF не предназначен для обеспечения удаленного доступа к объектам - он просто передает сообщения между клиентом и сервером.Следовательно, все, что вы можете выразить в XML-схеме (атомарные типы, что-то вроде наследования и композиции), может быть сериализовано и отправлено между двумя сторонами.

Все, что не может моделироваться в XML-схеме -Подобно обобщениям, интерфейсам, методам / коду - нельзя передавать между клиентом и сервером.

Существуют способы и приемы, позволяющие обойти это, если вы контролируете оба конца связи, и оба они основаны на .NET.По сути, вам придется поместить свой контракт на обслуживание и все ваши контракты на данные (все ваши классы) в отдельную сборку, на которую вы затем ссылаетесь как с сервера (реализующего контракт на обслуживание), так и с клиента, вызывающего контракт.Вы можете указать WCF повторно использовать типы, которые уже существуют в ссылочных сборках, и в этом случае клиент будет повторно использовать готовый класс Person (со всеми его достоинствами .NET) из вашей общей совместно используемой сборки вместопересоздание клиентского прокси-сервера данных.С помощью этого трюка вы можете сделать так, чтобы WCF отправлял сериализованные сообщения по сети, но на стороне клиента вы заново создаете полноценный объект .NET со всеми его методами и всеми.

Опять же: этопрекрасно работает, пока вы контролируете оба конца коммуникации, и оба конца используют .NET.Любая совместимость выходит за рамки этого подхода.

9 голосов
/ 06 ноября 2010

Вы смешиваете два понятия с вашим типом Person - то, что вы делаете, не сработает.

Вы поместили атрибут DataContract в тип Person.Это правильно, потому что у вас есть служба, которая возвращает Person.Person объект будет сериализован и возвращен вашему сервисному клиенту (CalculatorClient в данном случае).

Вы должны определить Person следующим образом:

[DataContract]
public class Person
{
    [DataMember]
    public string Description { get; set; }
}

И в вашемСлужба калькулятора:

public Person getPerson()
{ 
    Person tempPerson = new Person();
    tempPerson.Description = "This is a Person Object";
    return tempPerson; 
}

Это потому, что задача вашего Person объекта - хранить данные и переносить их с сервера на клиент.В его задачи не входит определение методов / операций, которые должны выполняться в ваших классах обслуживания (например, CalculatorService).Добавление атрибута OperationContract волшебным образом не превращает объект передачи данных в службу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...