Leandro.... me hiciste laburar.... :))) Bueno le dedique un rato al problema, no es que el tema me encanta...., y arme esto.
El uso seria asi, mira como se vería la clase: using System; using System.Collections.Generic; using System.Text; using AlgoDeAtributos00; namespace AlgoDeAtributos { public class AlgunaClase { private string[] propiedad; private string[] otraPropiedad; [LazyAttribute(typeof(ProviderA) )] public string[] Propiedad { get { propiedad=(string[])LazyFactoryHelper.InvokeLoad(propiedad); return propiedad; } set { propiedad = value; } } [LazyAttribute(typeof(ProviderB))] public string[] OtraPropiedad { get { otraPropiedad = (string[])LazyFactoryHelper.InvokeLoad(otraPropiedad); return otraPropiedad; } set { otraPropiedad = value; } } public AlgunaClase(){ } } } Antes de avanzar una aclaración, ahora el Lazy funciona como Lazy!!!!!!!!! Si la propiedad es null se carga, si es distinta de null se respeta el valor y no se toca.!!!!! Veamos el Helper: :))) using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.Reflection; namespace AlgoDeAtributos00 { public static class LazyFactoryHelper { public static object InvokeLoad(object destination) { if (destination == null) *// Aca se determina si hay que hacer la carga o no!!!!!!!* { StackTrace st = new StackTrace(false); MethodBase mb = st.GetFrame(1).GetMethod(); if (mb.IsSpecialName) *// Esto sirve para determinar si el llamador es una propiedad o un metodo !!!! * if (mb.Name.IndexOf("get_", 1, 1, StringComparison.OrdinalIgnoreCase)!=0)* // Verifica que sea el get de la propiedad !!!!* { PropertyInfo pi = mb.DeclaringType.GetProperty( mb.Name.Substring(4));* // Obtiene el PropertyInfo del invacador !!!!* foreach (LazyAttribute o in pi.GetCustomAttributes(typeof(LazyAttribute), false)) { *destination = (o.GetProvider() as Provider).GetItems(2); // Aqui se invoca la carga desde el provider obtenido por la factory!!!!! * } } } return destination; } } } Bue, te adjunto el ejemplo completo. Espero te guste y se ajuste a tu necesidad. Los tipos retornados dependen de lo que vos declares en tus providers, yo use string[] pero hubiera podido usar cualquier cosa. La contra de este método, va son dos como minimos, 1 *acoplamiento*, 2 Se explora el stacktrace y no es lo mas performante.... Lo bueno de este metodo, :) , es *desacoplado*. ( en definitiva estamos haciendo una forma de IoC ) La magia de Net.... Saludos Daniel Calvin PD: Contame si te gusto..... El día 16/11/07, Daniel Calvin <[EMAIL PROTECTED]> escribió: > > Hola Lenadro > > Ese codigo se puede evitar. > Hay que construir un helper que lo implemente. > > Si lo haces con un helper dentro de la propiedad deberías incluir la linea > que invoque al helper. > Menos de eso no se puede. > Si queres hacerlo en forma transparente, sin meter codigo dentro de la > propiedad, hay que hacer un poco mas de magia. > En ese caso la entidad la deberias instanciar desde una factory, ese > factory te retornaría una instancia de un proxy generado al vuelo para esa > entidad, el se encargaria de implementar el lazy en base al atributo. > > Si tengo un rato te escribo el código del helper con un lazy load real, > eso que escribi no es lazy load, fue solo una muestra de como invocar una > factory en base a un attibute. > > Te estoy mareando?..... > > Bue trato de hacerte un ejemplito mas serio. > > Saludos > > Daniel Calvin > > El día 16/11/07, Leandro Tuttini < [EMAIL PROTECTED]> escribió: > > > > > > Daniel, la verdad te pasaste muy buen codigo. > > > > Se que puede llegar a ser muy complejo, pero como evitaria ingresar este > > codigo: > > > > System.Reflection.PropertyInfo pi =this.GetType > > ().GetProperty("Propiedad"); > > foreach (LazyAtribute o in > > pi.GetCustomAttributes(typeof(LazyAtribute), > > false)) > > { > > propiedad=(o.GetProvider() as Provider).GetItems(2); > > } > > > > en la entidad, y colocarlo dentro del atributo. > > O es justo esta parte la que mencionabas realizarla con dinamic proxy. > > > > Como decia la intriga que tengo es como acceder a propiedad (o su > > variable privada) de la entidad desde dentro del atributo. > > Si es que esto se puede. > > > > Pero esta muy bueno el codigo, esta bueno como define que provider > > utilizar. > > > > Gracias > > > > > > *Daniel Calvin < [EMAIL PROTECTED]>* escribió: > > > > Hola Leandro > > > > No es muy lindo lo que vas a hacer, pero te doy una punta. > > Podes usar StackTrace para que el nombre de la propiedad que invoca al > > atributo sea dinamica, incluso podrias extraer parte del codigo y meterlo en > > un helper. > > > > El secreto esta en este pedacito: > > System.Reflection.PropertyInfo pi =this.GetType > > ().GetProperty("Propiedad"); > > foreach (LazyAtribute o in > > pi.GetCustomAttributes(typeof(LazyAtribute), > > false)) > > { > > propiedad=(o.GetProvider() as Provider).GetItems(2); > > } > > Es bastante mejorable si te pones. > > > > Tenes que tener en cuenta que es muy acoplado, pero, funciona. :)) > > > > Te adjunto un rar con la solucion completa, no se si no la filtrara el > > mug. > > Por las dudas te pego todo el código aca abajo. > > > > Saludos > > > > Daniel Calvin > > PD: Yo usaria proxies dinámicos.... :)) > > > > > > Tu clase sera algo asi si mal no entendi: > > using System; > > using System.Collections.Generic; > > using System.Text; > > using AlgoDeAtributos00; > > namespace AlgoDeAtributos > > { > > public class AlgunaClase > > { > > private string[] propiedad; > > > > [LazyAtribute(typeof(ProviderA))] > > public string[] Propiedad > > { > > get { > > System.Reflection.PropertyInfo pi =this.GetType > > ().GetProperty("Propiedad"); > > foreach (LazyAtribute o in > > pi.GetCustomAttributes(typeof(LazyAtribute), > > false)) > > { > > propiedad=(o.GetProvider() as Provider).GetItems(2); > > } > > return propiedad; > > } > > set { propiedad = value; } > > } > > [LazyAtribute(typeof(ProviderB))] > > public string[] OtraPropiedad > > { > > get > > { > > System.Reflection.PropertyInfo pi = > > this.GetType().GetProperty("OtraPropiedad"); > > > > foreach (LazyAtribute o in > > pi.GetCustomAttributes(typeof(LazyAtribute), > > false)) > > { > > propiedad = (o.GetProvider() as > > Provider).GetItems(2); > > } > > return propiedad; > > } > > set { propiedad = value; } > > } > > public AlgunaClase(){ } > > } > > } > > > > > > Bueno el programita de prueba seria algo asi: > > using System; > > using System.Collections.Generic; > > using System.Text; > > namespace AlgoDeAtributos > > { > > class Program > > { > > static void Main(string[] args) > > { > > AlgunaClase ac = new AlgunaClase(); > > foreach (string s in ac.Propiedad) > > Console.WriteLine(s); > > foreach (string s in ac.OtraPropiedad) > > Console.WriteLine(s); > > } > > } > > } > > La salida producida algo parecido a esto: > > Item uno > > Item dos > > Item unoPrima > > Item dosPrima > > > > Tu atributo LazyAttributte es algo asi: > > using System; > > using System.Collections.Generic; > > using System.Text; > > namespace AlgoDeAtributos00 > > { > > public class LazyAtribute:Attribute > > { > > private Provider provider =null; > > public LazyAtribute(Type factoryType) > > { > > this.provider = factoryType.InvokeMember("", > > System.Reflection.BindingFlags.CreateInstance, null, this.provider, > > null) as Provider; > > } > > public Provider GetProvider() { return provider; } > > } > > } > > Tus providers para que el ejemplo funcione serian: > > > > using System; > > using System.Collections.Generic; > > using System.Text; > > namespace AlgoDeAtributos00 > > { > > public abstract class Provider > > { > > public abstract string[] GetItems(int family); > > > > } > > public class ProviderA:Provider > > { > > public ProviderA() { } > > public override string[] GetItems(int family) { return new > > string[] { "Item uno", "Item dos" }; } > > } > > public class ProviderB : Provider > > { > > public ProviderB() { } > > public override string[] GetItems(int family) { return new > > string[] { "Item unoPrima", "Item dosPrima" }; } > > } > > } > > > > > > > > El día 15/11/07, Leandro Tuttini <[EMAIL PROTECTED]> > > escribió: > > > > > > Muchas gracias a todos por las respuestas. > > > > > > Les comento, la idea es hacer en un principio algo simple, la entidad > > > deberia poder utilizar los atributos y a este indicarle que Factory de > > > provider utilizar o es el especializado para cargar la propiedad. > > > Se que con esto queda medio acoplada la entidad pero seria la primer > > > version de prueba. > > > > > > En el final de seguro sera algo con dinamic proxy o algo asi, de > > > seguro al estilo que se utiliza en Castle project, > > > http://www.castleproject.org/dynamicproxy/index.html > > > > > > Si tienen ejemplos seran de mucha ayuda, que muestre como un atributo > > > se ejecute antes de la propiedad y que permita setear el valor de esta. > > > Cualquier ejemplo que vean pueden aportar sera de ayuda, y que por > > > supuesto puedan compartir. > > > Lo que no me termina de cerrar es como desde un atributo poder acceder > > > a la variable de la propiedad, para asignarle un valor. > > > > > > Diego muy bueno el ejemplo de codeproject, aunque por lo que vi > > > utiliza una libreria PostSharp, creo que el secreto esta en esta. > > > > > > Bueno voy a seguir analizando el tema. > > > Saludos > > > ** > > > ------------------------------ > > > > > > Los referentes más importantes en compra/venta de autos se juntaron: > > > Demotores y Yahoo!. Ahora comprar o vender tu auto es más fácil. > > > Visitá http://ar.autos.yahoo.com/ > > > > > > > > > > > -- > > Daniel A. Calvin > > Cooperator Team Member > > http://www.cooperator.com.ar > > Microsoft Certified Professional > > > > > > ------------------------------ > > > > Los referentes más importantes en compra/venta de autos se juntaron: > > Demotores y Yahoo!. Ahora comprar o vender tu auto es más fácil. > > Visitá http://ar.autos.yahoo.com/ > > > > > > > -- > Daniel A. Calvin > Cooperator Team Member > http://www.cooperator.com.ar > Microsoft Certified Professional > -- Daniel A. Calvin Cooperator Team Member http://www.cooperator.com.ar Microsoft Certified Professional
AlgoDeAtributos.rar
Description: Binary data