¿Cómo puedo hacer este sencillo trabajo de la fábrica de C # genéricos?
Pregunta
Tengo este diseño:
public interface IFactory<T> {
T Create();
T CreateWithSensibleDefaults();
}
public class AppleFactory : IFactory<Apple> { ... }
public class BananaFactory : IFactory<Banana> { ... }
// ...
El Apple
ficticio y Banana
aquí no comparten necesariamente los tipos comunes (que no sean object
, por supuesto).
Yo no quisiera que los clientes tienen que depender de las fábricas específicas, así que en vez, sólo puede pedir a un FactoryManager
de un nuevo tipo. Tiene un método FactoryForType
:
IFactory<T> FactoryForType<T>();
Ahora se puede invocar los métodos de interfaz apropiados con algo así como FactoryForType<Apple>().Create()
. Hasta ahora, todo bien.
Sin embargo, hay un problema en el nivel de aplicación: ¿Cómo almacenar esta correspondencia de los tipos de IFactory<T>
s? La respuesta es un ingenuo IDictionary<Type, IFactory<T>>
, pero eso no funciona ya que no hay ningún tipo de covarianza en el T
(estoy usando C # 3.5). ¿Solo estoy atascado con un IDictionary<Type, object>
y hacer la colada manualmente?
Solución
Lamentablemente sí le pegan con el casting manual. Sin embargo este casting puede ser un detalle de implementación y no visto por el consumidor. Por ejemplo
public class FactoryMap {
private Dictionary<Type,object> _map = new Dictionary<Type,object>();
public void Add<T>(IFactory<T> factory) {
_map[typeof(T)] = factory;
}
public IFactory<T> Get<T>() {
return (IFactory<T>)_map[typeof(T)];
}
}