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

Attachment: AlgoDeAtributos.rar
Description: Binary data

Responder a