2011-06-07 18 views
12

Tenemos una clase abstracta que es la base para una serie de solicitudes diferentes que enviamos a través de un servicio WCF. Es un truco feo y atroz que cada vez que agregamos una nueva solicitud, tenemos que recordar agregar el atributo [KnownType] a esta clase base.KnownType para todos los tipos derivados de una clase abstracta?

¿Hay alguna manera de decirle al DataContractSerializer que trate TODAS las derivaciones de este tipo abstracto como KnownType?

Respuesta

8

Tuve el mismo problema en un servicio de WCF e hice el siguiente truco "menos atroz" para evitar la limitación de tipo conocido. Estoy delineando solo por el hecho de mostrar opciones alternativas, depende de usted decidir si es mejor o no.

  1. al inicio del servicio, carga a través de la reflexión de los tipos desee exponer. P.ej. si todas las entidades expuestas a WCF derivan de una base abstracta común (o más), cargue todos los tipos del ensamblaje en el que se supone que se encuentran. Guarde en caché estos tipos estáticamente por razones de rendimiento.

  2. Crear un método estático que devuelve dichos tipos en caché, con la siguiente firma: public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)

  3. Marca la interfaz WCF con el siguiente atributo [ServiceKnownType("GetKnownTypes", typeof(StaticClassThatCachesTypes))]

Esto debería darle automática la exposición de todos los tipos que son o será derivado de la (s) clase (s) base de su elección, siempre y cuando el (los) desarrollador (es) futuro (s) las coloque (n) en el correcto como sembly

+0

Gracias por esto. Realmente no escala si hay múltiples tipos de base para diferentes tipos de contratos (tendrá que tener un helper estático para cada base) pero saca el elemento humano. :) – Joe

+0

@Joe: no necesariamente.Si tiene varias clases base, no hay nada que le impida cargar todos sus tipos derivados de una vez en el paso 1. GetKnownTypes debe devolver una lista de tipos. Las limitaciones reales son que debe conocer todas sus clases base (y adaptar el cargador de tipos cuando agrega una nueva), y debe saber dónde se encuentran. –

+0

Aceptando esto como una solución decente. Sería bueno tener algo un poco más inteligente a nivel de lenguaje/compilación ... – Joe

2

Otra opción además de la dada por Dan C. es cambiar al NetDataContractSerializer - no requiere declaraciones de tipos conocidos, ya que está estrechamente vinculado a la implementación del contrato exacto, por lo que deberá compartir el ensamblado que contiene los tipos entre el cliente y el servidor, y definitivamente perderá interoperabilidad en este escenario. Hay algunas publicaciones sobre cómo hacer eso (he visto this one pop-up en los resultados de google/bing a menudo).

+0

Sí, esperaba evitar esa dependencia. Gracias por la sugerencia, sin embargo. – Joe

-1

Here es un ejemplo de hacer esto con PostSharp. Mire hacia la parte inferior de la publicación.

-1

This es un ejemplo de lograr esto con IL Weaving usando Fody/Mono.Cecil.

Básicamente, se trata de una extensión Fody que inyecta KnownTypeAttributes durante el tiempo de construcción usando IL Weaving.

Durante la tubería de construcción, la extensión localiza todas las clases base marcadas con los KnowsDeriveTypes atributo (Parte de la extensión) y se añadirá el KnownTypeAttribute sobre todas las clases que se derivan (no necesariamente de manera directa) de uno de los anteriores clases base (con KnowsDeriveTyepsAttribute).

This es otro espejo para la publicación y here puede encontrar el repositorio Github para la extensión.

+0

No publique respuestas de solo enlace; si el enlace desaparece, esta es una publicación inútil. – Joe

+0

@Joe He agregado una breve explicación con más espejos para el enlace. No estoy seguro de que sea una buena idea explicar toda la publicación del blog en una respuesta de Stackoverflow. – m1o2

Cuestiones relacionadas