2012-05-15 17 views
7
public abstract Column<T> 
{ 
    private T Value {get;set;}  

    public abstract string Format(); 

} 

public class DateColumn : Column<DateTime> 
{ 
    public override string Format() 
    { 
     return Value.ToString("dd-MMM-yyyy"); 
    } 
} 

public class NumberColumn : Column<decimal> 
{ 
    public override string Format() 
    { 
     return Value.ToString(); 
    } 
} 

El problema que tengo es agregarlos a una colección genérica. Sé que es posible, pero ¿cómo puedo almacenar varios tipos en una colección etcDiferentes genéricos T en la misma colección

IList<Column<?>> columns = new List<Column<?>() 

Realmente agradecería cualquier consejo sobre la consecución de este objetivo. El objetivo es tener diferentes tipos de columna almacenados en la misma lista. Vale la pena mencionar que estoy usando NHibernate y el discriminador para cargar el objeto apropiado. Inicialmente, el valor debe tener el tipo de la clase.

Muchas gracias por su ayuda con anticipación.

+0

Me gustaría saber el punto de esto. Los genéricos ayudan con la seguridad del tipo. De todos modos, si realmente quisiera hacer esto, ¿no podría completar su lista con la Columna ? – Killnine

+0

No, eso no funcionó. He intentado utilizar una Columna . Creo que el problema realmente radica en tener el valor definido a través del polimorfismo y luego poder almacenarlo en una colección. Yo uso el discriminador para cargar los diferentes tipos de columnas. – Jonathan

+0

Hay [algunos] (http://stackoverflow.com/q/3215402/590790) [duplicados] (http://stackoverflow.com/q/3777057/590790) de esta pregunta. Además de la solución 'base-type' [publicada aquí por JaredPar] (http://stackoverflow.com/a/10606974/590790), me gustaría proponer [seguir el patrón del adaptador para crear un contenedor no genérico para este propósito] (http://stackoverflow.com/a/34417767/590790), por lo que el Principio de Sustitución de Liskov no está roto. –

Respuesta

13

Para que se almacenen juntas en un List<T>, las columnas deben tener un tipo de base común. La clase de base común más cercana de DateColumn y NumberColumn es object. Ninguno deriva de Column<T>, sino una instanciación específica y diferente de Column<T>.

Una solución a este problema es introducir un no genérico Column tipo que se deriva de Column<T> y almacenar que en el List

public abstract class Column { 
    public abstract object ValueUntyped { get; } 
} 

public abstract class Column<T> : Column { 
    public T Value { get; set; } 
    public override object ValueUntyped { get { return Value; } } 
} 

... 

IList<Column> list = new List<Column>(); 
list.Add(new DateColumn()); 
list.Add(new NumberColumn()); 
+5

También puede considerar la interfaz en lugar de la clase base. –

2

Los genéricos tienen que ver con la especificación del tipo. Si desea utilizar tipos dinámicos, utilice el clásico ArrayList en su lugar.

+2

En este caso, no creo que el OP desee el tipado dinámico, sino que quiere aprovechar los tipos de base y el comportamiento polimórfico – JaredPar

+0

Sí, está correcto @JaredPar Necesito analizar los valores y tratar de adivinar qué es un objeto es extremadamente difícil. – Jonathan

+2

Tienes razón, respondí +1 a tu respuesta detallada. – Pol

3

Probablemente tenga sentido derivar de una clase no genérica Column que envuelva la mayor parte de la interfaz común no genérica de una columna ... y luego declarar su lista como List<Column>.

+1

... y lo que dijo @JaredPar ... – spender

Cuestiones relacionadas