2009-09-17 26 views
6

Mam ten scenariusz, w którym metoda usługi internetowej, której używam w języku C#, zwraca obiekt biznesowy, podczas wywoływania metody usługi sieciowej za pomocą następującego kodu otrzymuję wyjątek "Nie można obsłużyć obiektu typu ContactInfo wpisać ContactInfo”w klasie reference.cs odniesienia internetowejNie można rzutować obiektu typu MyObject na typ MyObject

Kod:

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

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

Każda pomoc będzie mile widziane.

+0

Czy ostatnio aktualizowałeś swoją stronę internetową? – womp

Odpowiedz

10

Dzieje się tak, ponieważ jeden z obiektów ContactInfo jest serwerem proxy usługi WWW i znajduje się w innym obszarze nazw.

Jest to znany problem z usługami sieciowymi w stylu ASMX. W przeszłości zaimplementowałem automatyczną płytką kopię do obejścia tego (here's how, chociaż gdybym robił to ponownie, prawdopodobnie zamiast tego spojrzałbym na AutoMapper).

Na przykład, jeśli masz zespół z następujących klas:

MyProject.ContactInfo 

i wrócisz wystąpienie to z metodą internetowej:

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

Wtedy, kiedy dodać odwołanie WWW do twojego projektu klienta, otrzymujesz to:

MyClientProject.DoSomethingService.ContactInfo 

Oznacza to, że jeśli w kliencie ap plikacja, wywołać usługę internetową, aby uzyskać ContactInfo, masz taką sytuację:

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; 
      } 
     } 
    } 
} 

to na tym ostatnim wierszu że mogę korzystać ShallowCopy Klasa:

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); 
      } 
     } 
    } 
} 

UWAGA
To tylko działa, ponieważ klasa proxy i klasa "real" mają dokładnie takie same właściwości (jedna jest generowana z drugiej przez Visual Studio).

0

W jaki sposób odwołujesz się do klasy w projekcie usługi sieciowej, a także w projekcie konsumenckim? Jeśli po prostu użyłeś linku do pliku, może to wyjaśnić przyczynę błędu. Sposób serializowania działa dla .NET (Web Services lub w inny sposób, w jaki wierzę) polega na użyciu refleksji do załadowania/zrzutu danych obiektu. Jeśli pliki są po prostu połączone, to faktycznie są kompilowane do różnych typów w różnych zestawach, co wyjaśniałoby, dlaczego masz takie samo imię, ale nie możesz między nimi rzucać. Polecam tworzenie biblioteki "Core", która odnosi się zarówno do usług sieci Web, jak i do projektów konsumenckich, i zawiera klasę ContactInfo, której używa się wszędzie.

0

To nie jest problem - to funkcja.

Są to dwie niezależne klasy. Porównaj oba i zwróć uwagę, że klasa proxy nie ma żadnego konstruktora, metod, indeksorów ani innego zachowania z oryginalnej klasy. Jest to dokładnie to samo, co w przypadku korzystania z usługi ASMX w programie Java.

+1

@Dvvoter: chcesz, aby ktoś dbał o to, co myślisz? Wtedy będziesz musiał powiedzieć, co myślisz. "-2" niewiele mówi. Zamiast tego powiedz, dlaczego cofnąłeś. –

+0

Nie powinno się zachowywać w ten sposób. Problem ten występuje tylko w przypadku korzystania z generowanego proxy, a nie przy użyciu metody CreateChannel, ale nasz problem jest taki sam jak ten post. Nie sądzę, że ma to być funkcja. – schmoopy

+0

@schmoopy: używa usług sieci ASMX, a nie WCF. Nie ma metody "CreateChannel". –

1

Jak sugeruje kilka innych odpowiedzi, to dlatego, że .NET widzi je jako dwie różne klasy.Osobiście polecam używanie czegoś takiego jak AutoMapper. Używałem go i wydaje mi się to niesamowite. Możesz kopiować obiekty w 1-2 liniach kodu.

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

Wygląda na to, że masz dwie różne klasy po obu stronach. Twoja aplikacja ma klasę ContactInfo, a Twój serwis internetowy ma również klasę ContactInfo. Obie są dwiema zupełnie różnymi klasami. Jednym ze sposobów jest użycie klasy WebService po twojej stronie. Jeśli korzystasz z ContactInfo w swoim serwisie internetowym, to zostanie ono przekształcone do postaci szeregowej i będzie dostępne po stronie klienta do użytku.

1

W rzeczywistości nie jest to błąd. To problem ze zmianami wersji własnego projektu! Ponieważ podczas ostatniego uruchomienia nie używaj oryginalnych zaimportowanych referencji podczas kompilacji!

Na przykład tworzyłem serwer czatu, klienta. Użyłem struktury pakietów do przesyłania danych na temat projektu klienta. Następnie zaimportowano to samo odwołanie do projektu serwera.

Podczas przesyłania Packet packet = (Packet)binaryFormatter.Deserialize(stream); otrzymałem ten sam błąd. Ponieważ rzeczywiste odniesienie do pracy przy projekcie serwera nie jest teraz odniesieniem w projekcie klienta! Ponieważ wielokrotnie przebudowałem projekt klienta!

W przypadku odlewania <new object>=(<new object>) <old object> zawsze nowy obiekt musi być nowszą lub tą samą wersją co stary obiekt!

Zrobiłem więc oddzielny projekt, aby utworzyć bibliotekę DLL dla klasy Packet i zaimportowałem plik DLL do obu projektów.

Jeśli dokonałem jakiejkolwiek zmiany w klasie Packet, muszę ponownie zaimportować odniesienie do klienta i serwera.

Następnie odlewanie nie spowoduje powyższego wyjątku!

0

Można również zmodyfikować plik References.cs wygenerowany przez Visual Studio po dodaniu odwołania do strony internetowej. Jeśli usuniesz klasy generowane przez proxy i dodasz odniesienia (używając instrukcji) do swoich klas osobistych, będziesz mógł z nich korzystać od razu, bez płytkiej kopii/odbicia lub ciężkiego mapowania. (ale będziesz musiał ponownie zastosować modyfikację, jeśli zregenerujesz warstwę proxy).

Próbowałem również serializować obiekt proxy i deserializować go z powrotem w moich klasach DTO, ale był dość ciężki pod względem zasobów, więc w efekcie zmodyfikowałem warstwę referencyjną Cs.

nadzieję, że pomoże innym ludziom przychodzi tutaj :)

uprzejmie.

Powiązane problemy