2012-08-24 13 views
5

tengo 2 tipos: BaseQuestion y Question. Question hereda algunas propiedades de BaseQuestion. Ahora he creado una API web para hacer un BaseQuestion disponible. El tipo de datos Question tiene propiedades adicionales que no quiero poner a disposición. Tengo un método que recupera un Question y mi plan inicial era simplemente reubicarlo implícitamente en BaseQuestion. Pensé que perdería todas las propiedades adicionales que no quiero que sean accesibles y podría devolverlas. Bueno, no es así. Esto es lo que hago:C#: Superclase todavía tiene información subclase después de la conversión hacia arriba

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

El tipo de bq es todavía "Pregunta". No puedo acceder a las propiedades de BaseQuestion, pero aún puedo verlas en el depurador y están en el resultado JSON que envío al cliente.

¿Alguna idea sobre cómo puedo "forzar" a bq a ser del tipo BaseQuestion y no tener ninguna propiedad que esté definida en la subclase?

+0

El tipo de la variable es bq BaseQuestion. El tipo de tiempo de ejecución del objeto al que se refiere bq es Pregunta. No estoy seguro de lo que quiere decir con "force bq to be de type BaseQuestion".Solo podrá acceder a los miembros de BaseQuestion a través de la variable bq. – lesscode

+1

Creo que su confusión no es comprender que lo que ha dado son ** referencias ** a los objetos en la memoria. –

+0

Simon, buen punto. Entonces permítanme reformular: ¿Cómo puedo crear un nuevo objeto de tipo Pregunta y copiar automáticamente todos los valores de las propiedades? Por automáticamente quiero decir que no ** quiero ** implementarlo. En mi humilde opinión, este escenario no es exclusivo de mi situación y debería estar cubierto por .NET. – Jan

Respuesta

11

Encasillamiento no cambia la naturaleza del objeto, sólo cambia su punto de vista del objeto. Cuando encasillas al tipo base, estás mirando el objeto a través de un filtro que solo puede ver los miembros definidos en el tipo base, independientemente de cualquier otra cosa que esté definida en el objeto real.

Cuando regresa un objeto de una llamada de servicio web, que es el objeto real que será serializado y enviado de vuelta a través del cable - todos sus miembros serializable.

Una técnica que puede utilizar para evitar que los miembros de la clase de preguntas derivadas de ser devuelto a la persona que llama API es suprimir la serialización de los miembros declarados en la clase de preguntas. Existen varios subsistemas de serialización en .NET, pero si está utilizando XmlSerialization decoraría los miembros declarados en la clase Question con los atributos [XmlIgnore] para evitar que Serialization los serializara. Si está utilizando un subsistema de serialización diferente, necesitará averiguar el análogo de este en ese sistema.

Otra posibilidad es definir contratos de interfaz para su (s) servicio (s) web API. Sus clases BaseQuestion y Question implementarían una o más de esas interfaces de contrato. Creo que esto limitará la serialización a solo las propiedades definidas en la interfaz del contrato, independientemente de cuál sea el objeto real.

Si todo lo demás falla, la solución de fuerza bruta consiste en construir una instancia de su BaseQuestion en una var temporal, copiar las propiedades relevantes del objeto Question real al objeto temp y devolver el objeto temp. Esto es rudo y crudo y tiene que haber una mejor manera, pero funcionará.

+0

No puedo cambiar los tipos de Pregunta/BaseQuestion ya que la API web no es su único usuario. Estoy totalmente de acuerdo con la parte "debe haber una mejor manera", y he estado buscando por todo el lugar pero salió vacía. Creo que mi frustración es lo suficientemente grande como para crear un convertidor explícito. ¡Pero gracias por la ayuda! – Jan

+0

La mayor parte de esta respuesta es correcta, a excepción de la parte sobre la limitación de la serialización basada en la herencia de la interfaz. Esa parte no funciona porque no cambia el objeto original. Desearía que funcionara así :( –

+0

En lugar de crear una "interfaz de contrato", crea un "modelo de contrato" de lo que quieras serializar y deserializar. Escribe funciones de conversión o usa una biblioteca como [AutoMapper] (https: // github.com/AutoMapper/AutoMapper) para convertir su modelo "completo" a la versión reducida que solo contiene las propiedades que desea serializar. – MarioDS

1

Encasillamiento sólo cambia el tipo de la referencia al objeto, no el propio objeto.

Llamar a .GetType() en una instancia de Question siempre devolverá el tipo Question independientemente del tipo de variable que lo haga referencia.

Si desea que el tipo base, entonces tienes que llamar a la propiedad .BaseType del tipo.

Por lo tanto, algo como esto:

string type = q.GetType().BaseType.ToString(); 
+0

Eso fue solo para mostrar lo que quiero decir. Necesito tener un objeto que _only_ contiene las propiedades de la clase base. – Jan

+0

¿No es eso qué tipo de conversión le dará a 'BaseQuestion'? – Enigmativity

+0

Eso es lo que pensé, pero aparentemente no es así. No cambio el objeto en sí, solo cambio el contenedor que almaceno la referencia en. Las propiedades de la subclase siguen allí y se serializarán. – Jan

Cuestiones relacionadas