2009-04-29 13 views
5

Bellow se simplifica versión del código que tengo:Genérico problema generador de clases

public interface IControl<T> 
{ 
    T Value { get; } 
} 

public class BoolControl : IControl<bool> 
{ 
    public bool Value 
    { 
     get { return true; } 
    } 
} 

public class StringControl : IControl<string> 
{ 
    public string Value 
    { 
     get { return ""; } 
    } 
} 
public class ControlFactory 
{ 
    public IControl GetControl(string controlType) 
    { 
     switch (controlType) 
     { 
      case "Bool": 
       return new BoolControl(); 
      case "String": 
       return new StringControl(); 
     } 
     return null; 
    } 
} 

El problema está en el método de la clase GetControl ControlFactory. Porque devuelve IControl y solo tengo IControl < T> que es una interfaz genérica. No puedo proporcionar T porque en el caso de Bool va a funcionar como bool y en el caso de String va a ser una cadena.

¿Alguna idea de lo que tengo que hacer para que funcione?

Respuesta

5

Acaba de derivar IControl<T> de IControl.

public interface IControl<T> : IControl 
{ 
    T Value { get; } 
} 

ACTUALIZACIÓN

Si te missunterstood, y que no quiero una interfaz no genérico, que tendrá que realizar el método GetControl() genérica, también.

public IControl<T> GetControl<T>() 
{ 
    if (typeof(T) == typeof(Boolean)) 
    { 
     return new BoolControl(); // Will not compile. 
    } 
    else if (typeof(T) == typeof(String)) 
    { 
     return new StringControl(); // Will not compile. 
    } 
    else 
    { 
     return null; 
    } 
} 

Ahora usted tiene el problema de que los nuevos controles no pueden ser fundidas implícitamente a IControl<T> y que tendría que hacer esta explícita.

public IControl<T> GetControl<T>() 
{ 
    if (typeof(T) == typeof(Boolean)) 
    { 
     return new (IControl<T>)BoolControl(); 
    } 
    else if (typeof(T) == typeof(String)) 
    { 
     return (IControl<T>)new StringControl(); 
    } 
    else 
    { 
     return null; 
    } 
} 

ACTUALIZACIÓN

Un cambio en el reparto as IControl<T>-(IControl<T>). Esto es preferible porque causará una excepción si hay un error mientras as IControl<T> devuelve silenciosamente null.

3
public IControl<T> GetControl<T>() 
{ 
    switch (typeof(T).Name) 
    { 
     case "Bool": 
      return (IControl<T>) new BoolControl(); 
     case "String": 
      return (IControl<T>) new StringControl(); 
    } 
    return null; 
} 

Actualización; corrigió un par de errores en el código. Heres una llamada para obtener una clase:

IControl<bool> boolControl = GetControl<bool>(); 
+3

@Vadim - Le recomiendo encarecidamente que utilice la solución de Daniel, donde está comparando tipos en lugar de usar cadenas. Usar el nombre del tipo es más propenso a errores. –

+0

@Jon B: tienes razón; comparar los tipos proporcionará un código más robusto. Simplemente actualicé el código original de Vadim para trabajar. El enfoque de Daniel es la mejor manera de hacerlo. –

0

El tipo de devolución tiene que ser genérico, ya que, bueno, lo es. Piensa en cómo usarías esto. Devolver un objeto fuertemente tipado evita la necesidad de un método de fábrica genérico.

Incluso si pudiera hacerlo, ¿cuál es la ganancia de

IControl<bool> boolControl = controlFactory.GetControl("bool"); 

o, el que iba a funcionar,

IControl<bool> boolControl = controlFactory.GetControl<bool>("bool"); 

durante un determinado

IControl<bool> boolControl = controlFactory.GetBoolControl("bool"); 

De cualquier manera, tienes el interruptor() en el lado del cliente. Devuelve un objeto o tiene una interfaz IControl no tipada.

Cuestiones relacionadas