Невозможно привести объект типа MyObject к типу MyObject. - PullRequest
6 голосов
/ 17 сентября 2009

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

Код:

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

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

Любая помощь будет высоко ценится.

Ответы [ 7 ]

10 голосов
/ 17 сентября 2009

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

Это известная проблема с веб-сервисами в стиле asmx. В прошлом я использовал автоматическое мелкое копирование, чтобы обойти это (, вот как , хотя, если бы я делал это снова, я бы, вероятно, посмотрел на AutoMapper ).

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

MyProject.ContactInfo

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

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

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

MyClientProject.DoSomethingService.ContactInfo

Это означает, что если в вашем клиентском приложении вы вызываете веб-службу для получения 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).

1 голос
/ 15 января 2010

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

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

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

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

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

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

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

1 голос
/ 17 сентября 2009

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

Mapper.CreateMap<SourceClass, DestinationClass>();
destinationInstance = Mapper.Map<SourceClass, DestinationClass>(sourceInstance);
0 голосов
/ 24 мая 2011

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

Я также пытался сериализовать прокси-объект и десериализовать его обратно в мои классы DTO, но это было довольно много ресурсов, поэтому я в итоге изменил созданный слой References cs.

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

Пожалуйста.

0 голосов
/ 17 сентября 2009

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

0 голосов
/ 17 сентября 2009

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

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

0 голосов
/ 17 сентября 2009

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

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