Unable to pass base class (data contract) to derived class

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

I create an instance of SearchCriteria in my MVC controller action and try to convert it to CitySearchCriteria.

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

The citySearchCriteria object after the above statement shows a NULL value. I expected it to display both properties, CountryID and CityID with filled CountryID, and CityID blank ... but it sets the object to NULL.

What could be the solution? Does DataContract have anything with this?

The comments say that you cannot convert the base for output: but in fact, I did it successfully, in my opinion, it just doesn't work in the controller action:

 CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria; 

This converts successfully, so why doesn't it look like a controller?

+6
source share
3 answers

Everyone already (and correctly) told you that you simply cannot distinguish from Base to Derived, but it seems to me that you still do not understand why this line works in another fragment of your code:

 CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria; 

I think you are a little confused about what the “Type” of an instance is. You have not published a model definition, but I think you have something like this:

 public SearchCriteria SearchCriteria; 

This does not mean that SearchCriteria always contains instances of SearchCriteria, but only that it contains instances of types that can be added to SearchCriteria. In your case, it may contain instances of SearchCriteria or CitySearchCriteria. I suppose somewhere in your code you will find something like:

 Model.SearchCriteria = new CitySearchCriteria(); 

and this allows you to correctly execute yor cast. You can see that the instance is indeed a CitySearchCriteria (and not just an instance of SearchCriteria) executing this code immediately before the act:

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

To better understand, you could try changing the value in SearchCriteria just before your working cast, as shown below, only to find out that the actor will no longer work:

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

You cannot use this method!

If you do new , you create a new memory object of a certain size. In your case, new SearchCriteria() creates a new memory object with a sufficient size to hold one line, no more, no less.

In your last line, you do searchCriteria as CitySearchCriteria to apply the object in searchCriteria to the larger CitySearchCriteria type. But this is impossible. You are trying to "convert" a memory object that contains 1 line to a memory object that can contain 2 lines. But casting does not convert the new memory object. What will be the value of the new line? It just looks underwater to check if your searchCriteria link searchCriteria an object of type CitySearchCriteria . In your case: no (the object is of type searchCriteria ) and returns null .

So ... the following example WORKS (because CitySearchCriteria has already been created). This is also your solution:

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

And this does not work (since CitySearchCriteria has not yet been created). This is your situation:

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

This is the same as in the following example. This one works (since SearchCriteria has already been created):

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

And it does not (because SearchCriteria has not yet been created) ::

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

For the record: I would always use live translation, not a cast using as , unless you want to explicitly check if the object is of this type.

+6
source

You can create a CitySearchCriteria and transfer it to SearchCriteria. So you can see CountryId. You can later return it to CitySearchCriteria and see CountryId and CityId.

This has nothing to do with DataContract. The solution in your case would be to create a CitySearchCriteria and pass it to SearchCriteria (if you need it).

+2
source

Source: https://habr.com/ru/post/944339/


All Articles