Daniel, que tal.
La verdad te pasaste, el codigo esta genial.
Lo voy a chusmear mas en detalle, pero por lo que veo me viene regio.
Cualquier cosa vuelvo a molestar con alguna otro consulta.
Mil gracias.
Saludos
Daniel Calvin <[EMAIL PROTECTED]> escribió: 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
---------------------------------
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/