Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Superclass still has subclass info after upcast

I have 2 types: BaseQuestion and Question. Question inherits some properties from BaseQuestion. Now I have created a Web API to make a BaseQuestion available. The Question datatype has additional properties that I do not want to make available. I have a method that retrieves a Question and my initial plan was to just implicitly upcast it to BaseQuestion. I thought it would lose all extra properties that I do not want to make accessible and I could return it. Well, it doesn't. This is what I do:

Question q = allQuestions[0];
BaseQuestion bq = q;
string type = bq.GetType().ToString();

The type of bq is still "Question". I cannot access the BaseQuestion properties, but I can still see them in the debugger and they are in the JSON output that I send to the client.

Any ideas on how I can "force" bq to be of type BaseQuestion and not to have any properties that are defined in the subclass?

like image 612
Jan Avatar asked Aug 24 '12 02:08

Jan


2 Answers

Typecasting doesn't change the nature of the object, it only changes your view of the object. When you typecast to the base type, you're looking at the object through a filter that can only see the members defined on the base type, regardless of whatever else is defined in the actual object.

When you return an object from a web service call, it is the actual object that will be serialized and sent back across the wire - all of its serializable members.

One technique you could use to prevent members of the derived Question class from being returned to the API caller is to suppress serialization of the members declared in the Question class. There are several serialization subsystems in .NET, but if you're using XmlSerialization you would decorate the members declared in the Question class with [XmlIgnore] attributes to prevent them from being serialized by XmlSerialization. If you're using a different serialization subsystem you will need to figure out the analog of this in that system.

Another possibility is to define interface contracts for your web API service(s). Your BaseQuestion and Question classes would implement one or more of those contract interfaces. I believe this will limit the serialization to only the properties defined in the contract interface, regardless of what the actual object is.

If all else fails, the brute force solution is to construct an instance of your BaseQuestion in a temp var, copy the relevant properties from the actual Question object to the temp object, and return the temp object. This is rude and crude and there's got to be a better way, but it will work.

like image 155
dthorpe Avatar answered Oct 27 '22 02:10

dthorpe


Typecasting only changes the type of the reference to the object, not the object itself.

Calling .GetType() on an instance of Question will always return the Question type regardless of the variable type that references it.

If you want the base type then you need to call the .BaseType property on the type.

So, something like this:

string type = q.GetType().BaseType.ToString();
like image 29
Enigmativity Avatar answered Oct 27 '22 02:10

Enigmativity