2013-05-06 9 views
6
[DataContract] 
public class SearchCriteria 
{ 
    [DataMember] 
    public string CountryID { get; set; }  
} 

[DataContract] 
public class CitySearchCriteria: SearchCriteria 
{ 
    [DataMember] 
    public string CityID { get; set; } 
} 

sto creando un'istanza di SearchCriteria nella mia MVC azione del controller, e cercando di convertirlo in CitySearchCriteria.Impossibile eseguire il cast di classe di base (contratto di dati) per classe derivata

SearchCriteria searchCriteria = new SearchCriteria(); 
searchCriteria.CountryID = "1"; 
CitySearchCriteria citySearchCriteria = searchCriteria as CitySearchCriteria; 

L'oggetto "citySearchCriteria" dopo l'istruzione precedente mostra il valore NULL. Mi aspettavo che mostrasse entrambe le proprietà, CountryID e CityID con CountryID popolato, e CityID vuoto ... ma sta impostando l'oggetto su NULL.

Quale potrebbe essere la soluzione qui? DataContract ha qualcosa a che fare con questo?

I commenti sono suggerendo, non è possibile convertire una base per ricavare: ma in realtà, ho fatto questo successo a mio avviso, non è solo lavorando in azione di controllo:

CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria; 

Questa è la conversione con successo, quindi perché non la cosa simile che funziona nell'azione del controller?

+0

Non è possibile eseguire il cast da Base a Derivato. L'inverso è possibile – noobob

+0

si prega di consultare l'ultimo due paragrafo nella domanda – Nirman

+0

Controllare di nuovo la risposta di Martin (1 ° esempio). – noobob

risposta

5

Tutti hanno già (e correttamente) dichiarato che non è possibile eseguire il cast da Base a Derivato, ma mi sembra che non si riesca ancora a capire perché questa linea funzioni in un'altra parte del codice:

CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria; 

Penso che tu sia un po 'confuso su cosa sia il "Tipo" di un'istanza. Non hai pubblicare la definizione di modello, ma penso di avere qualcosa di simile:

public SearchCriteria SearchCriteria; 

Questo non vuol dire che SearchCriteria contiene sempre le istanze di SearchCriteria, ma solo che contiene le istanze di tipi che possono essere lanciato su SearchCriteria. Nel tuo caso può contenere istanze di SearchCriteria o di CitySearchCriteria. Suppongo che da qualche parte nel codice troverete qualcosa di simile:

Model.SearchCriteria = new CitySearchCriteria(); 

e questo è ciò che permette yor fuso che deve essere eseguito in modo corretto. Si può vedere che l'istanza è davvero una CitySearchCriteria (e non semplicemente un caso di Criteri di ricerca) l'esecuzione di questo codice appena prima il cast:

MessageBox.Show(Model.SearchCriteria.GetType().FullName; 

Per comprendere meglio si potrebbe tentare di modificare il valore in SearchCriteria poco prima del tuo lavoro cast come mostrato di seguito solo per scoprire che il cast non funzionerà più:

Model.SearchCriteria = new SearchCriteria(); 
MessageBox.Show(Model.SearchCriteria.GetType().FullName; 
CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria; 
+0

grazie, sì, hai ragione, ho avuto un sacco di confusione su questo. questi dettagli hanno chiarito lo stesso, e ho potuto vedere dove ho sbagliato a codificarlo. Grazie – Nirman

6

Non puoi lanciare in questo modo!

Se si esegue new, si crea un nuovo oggetto di memoria di una certa dimensione. Nel tuo caso new SearchCriteria() crea un nuovo oggetto di memoria con dimensioni sufficienti per contenere una stringa, niente di più, niente di meno.

Nell'ultima riga è necessario searchCriteria as CitySearchCriteria provare a trasmettere l'oggetto in searchCriteria a un tipo più grande CitySearchCriteria. Ma non può essere fatto. Stai provando a "convertire" un oggetto di memoria che contiene 1 stringa in un oggetto di memoria che può contenere 2 stringhe. Ma il casting non converte un nuovo oggetto di memoria. Quale sarebbe il valore della nuova stringa? Semplicemente guarda sott'acqua per verificare se il tuo riferimento searchCriteria contiene già un oggetto di tipo CitySearchCriteria. Nel tuo caso: non lo fa (l'oggetto è di tipo SearchCriteria) e restituisce null.

Quindi ... il prossimo esempio funziona (perché CitySearchCriteria è già stato creato). Questa è anche la soluzione:

SearchCriteria searchCriteria = new CitySearchCriteria(); 
CitySearchCriteria citySearchCriteria = searchCriteria as CitySearchCriteria; 

E questo non funziona (perché CitySearchCriteria NON è già stato creato). Questa è la tua situazione:

SearchCriteria searchCriteria = new SearchCriteria(); 
CitySearchCriteria citySearchCriteria = searchCriteria as CitySearchCriteria; 

È la stessa cosa del prossimo esempio.
Questo funziona (perché SearchCriteria è già stata creata):

object o = new SearchCriteria(); 
SearchCriteria searchCriteria = o as SearchCriteria; 

E questo non (perché SearchCriteria NON è già stato creato) ::

object o = new object(); 
SearchCriteria searchCriteria = o as SearchCriteria; 

Per la record: userei sempre un cast diretto, non un cast usando as, a meno che non si voglia testare esplicitamente se un oggetto è di quel tipo.

+0

Semplicemente non può essere convertito perché, in base alla sua implementazione, il cast non funzionerà dalla classe base a quella derivata. L'inverso è possibile. – noobob

+0

Penso che sia proprio quello che ho detto ... non è vero? O mi sto perdendo cosa intendi? Quale esempio nel mio testo non è corretto? –

+0

@noobob: quale è sbagliato? –

2

È possibile creare CitySearchCriteria e trasmetterlo a SearchCriteria. In questo modo puoi vedere solo CountryId. Successivamente, puoi restituirlo a CitySearchCriteria e vedere CountryId e CityId.

Questo non ha nulla a che fare con DataContract. Nel tuo caso, la soluzione sarebbe quella di creare CitySearchCriteria e trasmetterlo a SearchCriteria (se necessario).

+0

Ho trovato due domande simili: http://stackoverflow.com/questions/988658/unable-to-cast-from-parent-class-to-child-class e http://stackoverflow.com/questions/ 9885644/cast-the-parent-object-to-child-object-in-c-sharp – uross

+0

Il fatto è che, la mia vista è in attesa di un oggetto "SearchCriteria" perché è stato chiamato da più posti, che può avere "CitySearchCriteria" , "StateSearchCriteria", ecc. A seconda del controller e dell'azione chiamante. Inoltre, l'ho fatto con successo all'interno delle mie visualizzazioni, ad esempio CitySearchCriteria citySearchCriteria = (CitySearchCriteria) Model.SearchCriteria; e funziona bene, quindi perché non nell'azione del controller? – Nirman

Problemi correlati