2010-04-18 9 views
6

Sé que el título es un poco confuso pero desnudo conmigo. (Estoy a la espera de sugerencias sobre un nuevo título lol) Estoy escribiendo un TemplateEngine que me permitirá usar mi propio marcado en archivos basados ​​en texto. Estoy queriendo agregar controles como complementos a medida que la aplicación madura. He actualmente tiene una estructura como la siguiente:Cambiar el tipo de propiedad en la clase que implementa la interfaz con la propiedad tipo de objeto

interface IControl 
    string Id 
    object Value 

class Label : IControl 
    string Id 
    string Value 

class Repeater : IControl 
    string Id 
    List<IControl> Value 

Ahora vamos a ver la parte extraña de inmediato en la clase de repetidor con la propiedad Value. Esperaba que tener el tipo de valor como objeto en la interfaz me permitiera la flexibilidad de expandir los controles a medida que avanzaba. Al compilador no le gusta esto y por buenas razones, supongo.

Conclusión: Estoy intentando que todas las clases de control implementen la misma interfaz pero tengan diferentes tipos para la propiedad Value.

¿Alguien tiene alguna sugerencia de cómo lograr esto?

Nota: Por favor, no sugiera cosas como el uso de Spark View Engine para plantillas. Hay una razón por la que estoy creando trabajo extra para mí.

+0

¿Qué estás preguntando? – SLaks

+0

@SLaks: LOL Lo siento, podría necesitar tener un video que lo explique un poco mejor. tratar de entrar en más detalles podría dar como resultado una novela – used2could

+0

Estoy intentando que todas las clases de control implementen la misma interfaz pero tengan diferentes tipos para la propiedad Value. – used2could

Respuesta

8

Normalmente, el Repeater implementaría algo diferente, como un IItemsControl por ejemplo.

EDITAR 1

(eliminado por razones de brevedad)

EDIT 2

Ah bien, siempre se puede utilizar la implementación de interfaz explícita, por supuesto:

interface IControl 
{ 
    string Id { get; set; } 
    object Value { get; set; } 
} 

class Label : IControl 
{ 
    public string Id { get; set; } 
    public string Value { get; set; } 

    object IControl.Value 
    { 
     get { return this.Value; } 
     set { this.Value = (string)value; } 
    } 
} 

class Repeater : IControl 
{ 
    public string Id { get; set; } 
    public IList<IControl> Value { get; set; } 

    object IControl.Value 
    { 
     get { return this.Value; } 
     set { this.Value = (IList<IControl>)value; } 
    } 
} 
+0

sí, esta es la única otra ruta en la que podría pensar – used2could

+0

+1 para averiguar de qué mierda estaba hablando – used2could

+0

lolz ... simplemente entrenando mis habilidades de clarividencia: - > ... Actualicé mi respuesta con un ejemplo. – herzmeister

1

n , el compilador no permite que los campos del mismo nombre sean diferentes t tipos de datos distintos de lo que se define en la interfaz en clases derivadas.

Las propiedades (ya que no se permiten campos en la interfaz) deben implementarse en las clases derivadas y deben tener el mismo tipo de datos. Entonces, probablemente no puedas hacerlo con propiedades sin declaración explícita.

Sin embargo, si hace que una función devuelva valor, entonces funciona, pero debe verificar el tipo de retorno porque los tipos de retorno deben coincidir con la función; de lo contrario, se producirá un error al no implementar la función de la interfaz .

interface IControl 
    { 
     object Value(); 
    } 
    class A : IControl 
    { 
     string m_value = string.Empty; 
     public object Value() { return m_value; } 
    }; 
    class B : IControl 
    { 
     List<IControl> m_value = new List<IControl>(); 
     public object Value() { return m_value; } 
    }; 
    .... 
    object o = new B().Value(); 
    if (o is List<IControl>) 
     MessageBox.Show("List"); 

[Actualización]
Usted tiene que tener cuidado si definiendo explícitamente el cuerpo de las propiedades. Tener un nombre para dos propiedades sería peligroso si la implementación no se realiza con cuidado.

Estas dos propiedades si contienen una definición diferente, sería inexplicable para el uso final de la interfaz y las clases.

 public IList<IControl> Value 
     object IControl.Value 

ver este ejemplo:

... 
    class Repeater : IControl 
    { 
     List<IControl> m_Value = new List<IControl>(); 
     public IList<IControl> Value 
     { 
      get { return this.m_Value; } 
      set { this.m_Value = (IList<IControl>)value; } 
     } 
     object IControl.Value 
     { 
      get 
      { 
       return this.m_Value; 
      } 
      set 
      { 
       this.m_Value = new List<IControl>(); 
       this.m_Value.Add(new Label()); 
       this.m_Value.AddRange((List<IControl>)value); 
      } 
     } 
    } 
    ... 
    Repeater b = new Repeater(); 
    IControl i = b; 
    List<IControl> list = new List<IControl>(); 
    list.Add(new Repeater()); 
    i.Value = list; 

Se puede observar que el contenedor en la lista repetidor tendrá valores diferentes cuando se añade datos a través de IControl (debido a la definición explícita de IContainer.Value).

+0

+1 Gracias por señalar la preocupación de definir explícitamente una propiedad. – used2could

3

también se podría utilizar genéricos:

interface IControl<T> 
{ 
    string ID{get;set;} 
    T Value{get;set;} 
} 

class SomeControl : IControl<string> 
{ 
    public string ID{get;set} 
    public string Value{get;set;} 
} 

class SomeOtherControl : IControl<int> 
{ 
    public string ID{get;set} 
    public int Value{get;set;} 
} 

me gusta esto mejor que la idea de interfaz explícita si es sólo un valor de retorno que tiene que cambiar. Sin embargo, creo que si tuviera varias propiedades en las que cada una devolvería un tipo diferente, no le gustaría tener IControl. Al menos, no lo haría. En ese caso, recomendaría las interfaces explícitas.

Por supuesto, esto no funcionaría si no tuviera acceso a la fuente de IControl.

Editar: tuvo un error tipográfico. Corregido

+0

sí, podríamos usar genéricos también, no lo he pensado porque me han lavado el cerebro mediante herramientas de diseño de interfaz de usuario a las que, en general, no les gustan los controles con parámetros genéricos. ;-) – herzmeister

+0

Pensé en los genéricos y fue rechazado por la gerencia. Algo no es fácil para los desarrolladores que no están familiarizados con los detalles de la biblioteca ... (Solo cobro un cheque) – used2could

Cuestiones relacionadas