2009-09-17 14 views
6

Ho questo scenario in cui un metodo webservice che sto utilizzando in C# restituisce un oggetto Business, quando chiama il metodo webservice con il seguente codice ottengo l'eccezione "Impossibile eseguire il cast dell'oggetto di tipo ContactInfo digitare ContactInfo" nella classe Reference.cs del riferimento webImpossibile eseguire il cast dell'oggetto di tipo MyObject per digitare MyObject

Codice:

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

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

Qualsiasi aiuto sarebbe molto apprezzato.

+0

Hai aggiornato la tua pagina web ultimamente? – womp

risposta

10

Questo perché uno degli oggetti ContactInfo è un proxy del servizio Web e si trova in uno spazio dei nomi diverso.

È un problema noto con i servizi Web in stile asmx. In passato ho implementato la copia superficiale automatica per aggirare il problema (here's how, sebbene se lo stessi facendo di nuovo probabilmente guarderei allo AutoMapper).

Ad esempio, se si dispone di un assieme con la seguente classe:

MyProject.ContactInfo 

e si ritorna un'istanza di esso da un metodo Web:

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

Poi, quando si aggiungere il riferimento web al progetto cliente, in realtà si ottiene questo:

MyClientProject.DoSomethingService.ContactInfo 

questo significa che se, nel vostro ap cliente plicatura, si chiama il servizio web per ottenere un ContactInfo, si ha questa situazione:

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

E 'su quella ultima linea che io uso il mio ShallowCopy classe:

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

NOTA
Questo solo funziona perché la classe proxy e la classe "reale" hanno esattamente le stesse proprietà (una viene generata dall'altra da Visual Studio).

0

Come si fa riferimento alla classe nel progetto di servizio Web e nel progetto del consumatore? Se hai semplicemente usato un collegamento al file, questo potrebbe spiegare la causa dell'errore. Il modo in cui la serializzazione funziona per .NET (Web Services o altrimenti credo) è utilizzando la reflection per caricare/scaricare i dati di un oggetto. Se i file sono semplicemente collegati, in realtà vengono compilati in tipi diversi in diversi assembly, il che spiegherebbe il motivo per cui si ha lo stesso nome ma non è possibile effettuare il cast tra di essi. Raccomando di creare una libreria "Core" che sia il riferimento al web service e al progetto del consumatore, e contenga la classe ContactInfo che usi ovunque.

0

Questo non è un problema, è una funzionalità.

Sono due classi indipendenti. Confrontate i due e notate che la classe proxy non ha costruttori, metodi, indicizzatori o altri comportamenti della classe originale. Questa è esattamente la stessa cosa che succederebbe se si consumasse il servizio ASMX con un programma Java.

+1

@Downvoter: vuoi che qualcuno si interessi di ciò che pensi? Quindi dovrai dire quello che pensi. "-2" non dice molto. Invece, dì perché hai downvoted. –

+0

Non dovrebbe comportarsi in questo modo. Abbiamo questo problema quando si utilizza un proxy generato, non quando si utilizza il metodo CreateChannel, ma il nostro problema è lo stesso di questo post. Non penso che questo sia pensato per essere una caratteristica. – schmoopy

+0

@schmoopy: sta utilizzando i servizi Web ASMX, non WCF. Non esiste un metodo 'CreateChannel'. –

1

Come molte altre risposte hanno suggerito, è perché .NET le vede come due classi diverse.Personalmente raccomanderei di usare qualcosa come AutoMapper. L'ho usato e mi sembra davvero fantastico. Puoi copiare i tuoi oggetti in 1-2 righe di codice.

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

Sembra che tu abbia due classi diverse su entrambe le estremità. La tua applicazione ha la classe ContactInfo e il tuo webservice ha anche la classe ContactInfo. Entrambi sono due classi completamente diverse. Un modo è utilizzare la classe WebService dalla tua parte. Se si utilizza ContactInfo all'interno del proprio servizio Web, questo verrà serializzato e sarà disponibile sul lato client per l'uso.

1

In realtà questo non è un bug. È un problema con le modifiche alla versione del tuo progetto! Poiché la tua corsa finale non usa i riferimenti originali importati su compilazione!

Ad esempio, stavo creando un server di chat, client. Ho usato una struttura a pacchetto per trasmettere dati sul progetto del cliente. Quindi ha importato lo stesso riferimento al progetto del server.

Durante il casting Packet packet = (Packet)binaryFormatter.Deserialize(stream); ho ricevuto lo stesso errore. Perché il riferimento effettivo al progetto del server non è il riferimento ora al progetto client! Perché ho ricostruito il progetto client molte volte dopo!

Nel casting <new object>=(<new object>) <old object> il nuovo oggetto deve sempre essere una versione più nuova o uguale a quella del vecchio oggetto!

Quindi quello che ho fatto è stato creare un progetto separato per creare una DLL per la classe Packet e importare il file DLL in entrambi i progetti.

Se ho apportato qualche modifica alla classe Packet, devo importare nuovamente il riferimento a client e server.

Quindi il casting non darà l'eccezione di cui sopra!

0

È inoltre possibile modificare il file References.cs generato da Visual Studio quando viene aggiunto il riferimento Web. Se rimuovi le classi generate dai proxy e aggiungi un riferimento (usando le istruzioni) alle tue classi personali, sarai in grado di usarle subito, senza una copia/riflessione superficiale o una mappatura pesante. (ma dovrai riapplicare la tua modifica se rigeneri il livello proxy).

Ho anche provato a serializzare l'oggetto proxy e deserializzare di nuovo nelle mie classi DTO, ma era abbastanza pesante risorse così ho finito per modificare il livello generato dai riferimenti cs.

auguro che possa aiutare altre persone a venire qui :)

Gentilmente.

Problemi correlati