2009-09-17 2 views
6

У меня такой сценарий, когда метод webservice, который я потребляю в C#, возвращает объект Business, при вызове метода webservice со следующим кодом я получаю исключение «Невозможно выполнить листинг объекта типа ContactInfo к типу CONTACTINFO»в классе Reference.cs веб-ссылкиНевозможно лить объект типа MyObject для ввода MyObject

Код:

ContactInfo contactInfo = new ContactInfo(); 
Contact contact = new Contact(); 

contactInfo = contact.Load(this.ContactID.Value); 

Любая помощь будет оценена.

+0

Вы обновили свой веб-справочник в последнее время? – womp

ответ

10

Это связано с тем, что один из объектов ContactInfo является прокси-сервером веб-службы и находится в другом пространстве имен.

Это известная проблема с веб-службами в стиле asmx. Раньше я реализовал автоматическую мелкую копию, чтобы обойти ее (here's how, хотя, если бы я делал это снова, я бы, вероятно, посмотрел на AutoMapper).

Например, если у вас есть узел со следующим классом:

MyProject.ContactInfo 

и вы возвращаете его экземпляр с веб-метода:

public class DoSomethingService : System.Web.Services.WebService 
{ 
    public MyProject.ContactInfo GetContactInfo(int id) 
    { 
     // Code here... 
    } 
} 

Затем при добавлении веб-ссылки к вашему проекту клиента, вы на самом деле получаете это:

MyClientProject.DoSomethingService.ContactInfo 

Это означает, что если в вашем клиенте ap складка, вы вызываете веб-службу, чтобы получить ContactInfo, то такая ситуация:

namespace MyClientProject 
{ 
    public class MyClientClass 
    { 
     public void AskWebServiceForContactInfo() 
     { 
      using (var service = new DoSomethingService()) 
      { 
       MyClientProject.DoSomethingService.ContactInfo contactInfo = service.GetContactInfo(1); 

       // ERROR: You can't cast this: 
       MyProject.ContactInfo localContactInfo = contactInfo; 
      } 
     } 
    } 
} 

Это на этой последней строке, что я использую мой ShallowCopy класс:

namespace MyClientProject 
{ 
    public class MyClientClass 
    { 
     public void AskWebServiceForContactInfo() 
     { 
      using (var service = new DoSomethingService()) 
      { 
       MyClientProject.DoSomethingService.ContactInfo contactInfo = service.GetContactInfo(1); 

       // We actually get a new object here, of the correct namespace 
       MyProject.ContactInfo localContactInfo = ShallowCopy.Copy<MyClientProject.DoSomethingService.ContactInfo, MyProject.ContactInfo>(contactInfo); 
      } 
     } 
    } 
} 

ПРИМЕЧАНИЕ
Это только работает, потому что прокси-класс и «реальный» класс имеют точно такие же свойства (один из них генерируется Visual Studio).

0

Как вы ссылаетесь на класс в своем проекте веб-сервиса, а также на потребительский проект? Если вы просто использовали ссылку на файл, это может объяснить причину ошибки. Способ serialialation работает для .NET (веб-службы или, как я полагаю, я полагаю), используя рефлексию для загрузки/выгрузки данных объекта. Если файлы просто связаны друг с другом, они фактически собираются для разных типов в разных сборках, что объясняет, почему у вас одно и то же имя, но не может отличать их. Я рекомендую создать библиотеку «Core», которая ссылается как на веб-службу, так и на проекты потребительских проектов, и содержит класс ContactInfo, который вы используете повсюду.

0

Это не проблема - это особенность.

Это два независимых класса. Сравните два и обратите внимание, что в прокси-классе нет ни одного из конструкторов, методов, индексаторов или другого поведения из исходного класса. Это то же самое, что и в случае использования службы ASMX с помощью Java-программы.

+1

@ Downvoter: хотите, чтобы кто-то заботился о том, что вы думаете? Тогда вам придется сказать, что вы думаете. «-2» не говорит много. Вместо этого скажите, почему вы отказались. –

+0

Это не должно вести себя так. У нас есть эта проблема при использовании только сгенерированного прокси, а не при использовании метода CreateChannel, но наша проблема такая же, как и этот пост. Я не думаю, что это должно быть особенностью. – schmoopy

+0

@schmoopy: он использует веб-службы ASMX, а не WCF. Нет метода CreateChannel. –

1

Как уже было сказано несколькими другими ответами, это связано с тем, что .NET рассматривает их как два разных класса.Я лично рекомендовал бы использовать что-то вроде AutoMapper. Я использую его, и это кажется довольно удивительным. Вы можете копировать свои объекты в 1-2 строках кода.

Mapper.CreateMap<SourceClass, DestinationClass>(); 
destinationInstance = Mapper.Map<SourceClass, DestinationClass>(sourceInstance); 
0

Похоже, у вас есть два разных класса на обоих концах. В вашем приложении есть класс ContactInfo, а ваш веб-сервис также имеет класс ContactInfo. Оба являются двумя совершенно разными классами. Один из способов - использовать класс WebService на вашей стороне. Если вы используете ContactInfo внутри своего веб-сервиса, он будет сериализован и будет доступен на стороне клиента для использования.

1

На самом деле это не ошибка. Это проблема с изменением версии вашего собственного проекта! Поскольку ваш окончательный запуск не использует исходные импортированные ссылки при компиляции!

Например, я делал чат-сервер, клиент. Я использовал структуру пакетов для передачи данных по проекту клиента. Затем импортируется та же ссылка на серверный проект.

При отливке Packet packet = (Packet)binaryFormatter.Deserialize(stream); У меня такая же ошибка. Поскольку фактическая ссылка на проект сервера не является ссылкой на проект клиента! Потому что я многократно перестраивал клиентский проект!

В литье <new object>=(<new object>) <old object> всегда новый объект должен быть более новой или такой же, как старый объект!

Итак, я сделал отдельный проект для создания DLL для класса Packet и импортировал DLL-файл в оба проекта.

Если я сделал какое-либо изменение класса Packet, мне нужно снова импортировать ссылку на клиент и сервер.

Тогда кастинг не даст вышеизложенного исключения!

0

Вы также можете изменить файл References.cs, сгенерированный Visual Studio, при добавлении веб-ссылки. Если вы удалите классы, созданные с помощью прокси-сервера, и добавьте ссылку (используя утверждения) в свои персональные классы, вы сможете использовать их сразу, без мелкой копии/отражения или тяжелого отображения. (но вам придется повторно применить свою модификацию, если вы обновите прокси-уровень).

Я также попытался сериализовать прокси-объект и десериализовать их обратно в своих классах DTO, но это был довольно тяжелый ресурс, поэтому я закончил модификацию слоя, сгенерированного ссылками Cs.

Надеется, что это поможет другим людям приходить сюда :)

Пожалуйста.

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