Monday, September 25, 2006

Fabrica generica para el patron de creacion sencillo en C#

La ultima vez les presente el simple factory pattern usando diccionarios de metodos en C# y tambien les conte de la implementacion (mucho mas elegante y generica) que Steven escribio; con la cual ya no necesitamos escribir una fabrica nueva para cada serie de productos, sino que podemos usar esta fabrica para cualquier producto que tengamos. Aun cuando la generacion dinamica de codigo esta muy suave, yo me quede inquietado con la idea de que tal vez habia una manera mas facil de lograr esa misma tarea, finalmente me llego la inspiracion y escribi una version mucho mas corta. Aqui esta:

public static class SimpleStaticGenericFactory<TKey, TBaseType> where TBaseType : class {
public delegate TBaseType BaseTypeInvoker();
private static Dictionary<TKey, BaseTypeInvoker> methods =
new Dictionary<TKey, BaseTypeInvoker>();
public static void Add(TKey key, BaseTypeInvoker instantiatorMethod) {
if (!methods.ContainsKey(key))
methods.Add(key, instantiatorMethod);
}
public static void CreateInstance(TKey key) {
if (methods.ContainsKey(key))
methods[key]();
else //what would you like to do in this case?
throw new ArgumentException(string.Format("{0} not found", key));
}
}

Eso es todo!, o si prefieres la version no-estatica:

public class SimpleGenericFactory<TKey, TBaseType> where TBaseType : class {
public delegate TBaseType BaseTypeInvoker();
private Dictionary<TKey, BaseTypeInvoker> methods =
new Dictionary<TKey, BaseTypeInvoker>();
public void Add(TKey key, BaseTypeInvoker instantiatorMethod) {
if (!methods.ContainsKey(key))
methods.Add(key, instantiatorMethod);
}
public void CreateInstance(TKey key) {
if (methods.ContainsKey(key))
methods[key]();
else //what would you like to do in this case?
throw new ArgumentException(string.Format("{0} not found", key));
}
}

Realmente *no necesitamos* el metodo CreateInstance, podriamos llamar los metodos directamente si el diccionario fuera publico, pero no seria muy buena idea dar acceso abierto al diccionario (aunque con refleccion se puede lograr, pero ya les contare). Usando el ejemplo de los reportes que he venido usando, podriamos usar esta fabrica generica de la siguiente manera:

SimpleStaticGenericFactory<string, BaseReport>.Add("report1", delegate() { return new Report1(); });
SimpleStaticGenericFactory<string, BaseReport>.Add("report2", delegate() { return new Report2(); });
SimpleStaticGenericFactory<string, BaseReport>.CreateInstance("report1");
o usando la version no-estatica:
SimpleGenericFactory<string, BaseReport> reports1 =
new SimpleGenericFactory<string, BaseReport>();
reports1.Add("report1", delegate() { return new Report1(); });
reports1.Add("report2", delegate() { return new Report2(); });
reports1.CreateInstance("report1");
simple, sencillo y elegante; voy a escribir un ejemplo de un modelo plug-in que utilice esta fabrica para que vean lo flexible de esta fabrica generica.

kick it on DotNetKicks.com

3 comments:

Paran0ide said...

hola como estas, encontre genial tu articulo de fabrica de código, estoy desarrollando una especia de IDE simple a base de plug-ins y un script de programación tipo c# con generación de código dinámico, al final de este post hablas de un ejemplo de arquitectura de plug-ins, me gustaría saber y si no fuera mucho aprovechamiento de mi parte si es que publicaste ese demo en el blog, o si es que puede orientarme un poco sobre el tema, ya que mi problema es el instanciar objetos (plug-ins) que son de clases de distinto tipo sin propiedades, metodos, eventos en común, he visto ejemplos de arquitectura de plug in a través de interfaces pero eso me obliga a tener un modelo statico de metodos y eventos, espero me puedas ayudar, saludos


y gracias de ante mano
bye

Paran0ide said...

me falto felicitarte, muy buen blog. hay mucha información interesante y valiosa.

BlackTigerX said...

@Paran0ide - gracias por la visita y tu interes en el tema, este post fue escrito hace ya un buen tiempo, y yo lo utilice para crear dicha arquitectura de plugins y hoy en dia esta funcionando en muchos sistemas en produccion, lo que pasa que en ese timepo no habia una solucion de terceros para este tipo de proyectos, pero hoy en dia si esta disponible, y mas que probada (usada nada mas y nada menos que para crear el mismisimo Visual Studio 2010), asi que es lo que te voy a recomendar que uses tu, esta libreria es MEF ahi te dejo el link, ahi mismo encontraras demos de como funciona

salu2