c# - tercero - ¿Cuál es la mejor manera de representar una bolsa de propiedad con seguridad de tipo en una clase?
representaciones graficas tablas (2)
Tengo una aplicación de terceros que proporciona un objeto con muchos "atributos", que son simplemente pares de claves (cadena) y valores. Los tipos de valores pueden ser cadenas, DateTime, Int32 o Int64.
Necesito crear mi propia clase para representar este objeto, de una manera conveniente. Estoy creando un servicio WCF que proporciona este objeto a los clientes, por lo que necesito que sea muy fácil y limpio.
Las claves de los atributos se presentarán como Enum para los clientes (para ocultar la información de las cadenas clave específicas de la aplicación de terceros). Sin embargo, no estoy seguro de cómo representar los valores. Estas son algunas de las opciones:
Opción 1: tener diferentes colecciones por valor de atributo, parece feo pero será muy fácil de usar para los clientes
public class MyObject
{
public Dictionary<MyTextAttributeKeysEnum, string> TextAttributes { get; set; }
public Dictionary<MyDateAttributeKeysEnum, DateTime> DateAttributes { get; set; }
public Dictionary<MyNumAttributeKeysEnum, long> NumericAttributes { get; set; }
public string Name { get; set; }
public string Id{ get; set; }
Opción 2: Convierta todos los atributos en cadenas
public class MyObject
{
public Dictionary<MyAttributeKeysEnum, string> MyAttributes { get; set; }
public string Name { get; set; }
public string Id{ get; set; }
Opción 3: mantenerlos como objetos, dejar que los clientes se molesten con el moldeado y la conversión
public class MyObject
{
public Dictionary<MyAttributeKeysEnum, object> MyAttributes { get; set; }
public string Name { get; set; }
public string Id{ get; set; }
¿Qué le parece hacer que la clase DataContract sea abstracta y proporcionar diccionarios con los tipos que necesita en las clases derivadas?
[DataContract]
[KnownType(typeof(My3dPartyObjectString))]
[KnownType(typeof(My3dPartyObjectInt64))]
public abstract class My3dPartyObjectBase
{
// some common properties
}
[DataContract]
public class My3dPartyObjectString : My3dPartyObjectBase
{
public Dictionary<3PAttributeKeysEnum, string> MyStringAttributes { get; set; }
}
[DataContract]
public class My3dPartyObjectInt64 : My3dPartyObjectBase
{
public Dictionary<3PAttributeKeysEnum, long> MyStringAttributes { get; set; }
}
Entonces el cliente tendrá que analizar el tipo real de objeto devuelto y obtener una colección de atributos en función del tipo. Eso estaría cerca de su opción 3d, pero el cliente al menos tendrá algún tipo de seguridad en el nivel de objeto de respuesta.
Usar varios diccionarios simplemente no se ve bien :) Pero podría funcionar en algunos escenarios.
Si está absolutamente seguro de que la cuerda es suficiente para todos, vaya con cuerdas. Pero si algún otro código necesitara analizarlo, eso va a ser costoso.
Si quieres una solución sencilla y simple, solo tienes que ir con objetos. Aunque introduciría el boxeo / unboxing para los tipos de valor (olvídelo si no opera miles de objetos) y perdería información sobre valores, esta solución podría funcionar bien.
También podría considerar la introducción de una clase intermedia para un valor. Algo como
public Dictionary<MyAttributeKeysEnum, PropertyBagValue> MyAttributes { get; set; }
public class PropertyBagValue
{
public object AsObject { get; set; }
public string AsString { get; set; }
public int AsInt { get; set; }
// ...
}
Internamente puede almacenar su valor en una variable del tipo original (int en una variable int, cadena en una variable de cadena, etc., es decir, tener una variable separada para cada tipo) y luego puede evitar la conversión de tipo. También podría envolver su diccionario en otra clase, agregar algunos accesorios útiles y hacer que se vea mejor. Sin embargo, no sé cómo encaja esto en su infraestructura.