Можно ли возвращать интерфейсы из .net webservices или можно возвращать только конкретные классы? - PullRequest
7 голосов
/ 28 января 2009

Мне нужно вернуть сложный тип из веб-сервиса и сконструировал класс MyComplexType, который реализует интерфейс IMyComplexType. Теперь в моем веб-сервисе у меня есть метод, который должен возвращать объект, который реализует IMyComplexType следующим образом:

[WebMethod]
public IMyComplexType GetMyComplexType()
{
   IMyComplexType myCt = new MyComplexType();
   ...
   return myCt; 
}

Все компилируется нормально, но когда я запускаю веб-сервис, он выдает исключение следующим образом:

System.NotSupportedException: Cannot serialize interface MyWebService.IMyComplexType.

Это умышленно или я что-то упустил. Могу ли я как-то украсить свой класс или интерфейс, чтобы это позволить? Нужно ли удалять все интерфейсы и работать только с конкретными и, возможно, абстрактными базовыми классами, чтобы иметь возможность делать это с веб-сервисами .net?

Edit:

это интерфейс, который я пытаюсь сериализовать:

public interface ICustomer
{
     long Id {get; set;}
     string Name {get; set;}
     string EmailAddress {get; set;}
}

Ответы [ 3 ]

2 голосов
/ 29 января 2009

Короткий ответ - нет, вы не можете вернуть интерфейс через WebService.

Длинный ответ заключается в том, что вы можете получить желаемое поведение, но оно немного хакерское. Решение состоит в том, чтобы использовать двоичную сериализацию. Таким образом, вы сериализуете свой тип в байты, веб-метод возвращает последовательность байтов, а затем, с другой стороны, вы десериализуете байты обратно в ваш сложный тип.

Например

[WebMethod]
public byte[] GetMyComplexType()
{

   IMyComplexType myCt = new MyComplexType();
   ...

   MemoryStream stream = new MemoryStream();
   IFormatter fmt = new BinaryFormatter();
   fmt.Serialize(stream, myCt);
   stream.Flush();
   byte[] bytes = stream.ToArray();
   stream.Close();

   return bytes;
}

Вам нужно будет преобразовать все обратно на другом конце.

byte[] bytes = service.GetMyComplexType();
MemoryStream stream = new MemoryStream(bytes);
BinaryFormatter fmt = new BinaryFomatter();
MyComplexType myCt = fmt.DeSerialize(stream);

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

В качестве альтернативы, если они являются вашими интерфейсами, вы могли бы превратить их в абстрактные классы. Однако это не будет работать, если вы хотите, чтобы класс реализовывал несколько интерфейсов (или вы уже наследовали от другого класса), поскольку вы можете наследовать только один класс. Если вам нужно какое-то полиморфное поведение на клиенте, вам нужно использовать атрибут XmlInclude.

0 голосов
/ 28 января 2009

Вам не нужно реализовывать ISerializable - достаточно просто пометить интерфейс атрибутом Serializable. Если вы хотите реализовать интерфейс, во что бы то ни стало, продолжайте - он даст вам детальный контроль над сериализацией интерфейса. Но я думаю, что реализация по умолчанию должна быть в порядке. Также убедитесь, что все элементы интерфейса также сериализуемы.

[Редактировать] Я даже не думал об этом прямо - нет никакого способа, которым вы сможете реализовать ISerializable, поскольку вы все равно пытаетесь сериализовать интерфейс. Место, где ISerializable будет подходящим, будет на пользовательских типах, которые нуждаются в настраиваемой сериализации, предоставляемой интерфейсом.

0 голосов
/ 28 января 2009

Это было давно, но я считаю, что вам нужно только расширить свои интерфейсы ISerializable и все должно быть хорошо.

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