Número 50julio-AGOSTO 2008

Visual Basic•C#•ASP.NET•ADO.NET•AJAXSilverlight.NET Framework

dotNetManía

Revista dedicada a los profesionales de la plataforma .NET

Menú

Inicio

Números publicados

Libros

Próximo número (nº51)

Autores

¿Qué es dotNetManía?

Garantía de satisfacción

Contactar

Pedidos

Suscripciones

Renovaciones

Libros

Noticias dnm

Alhambra-Eidos llega a un acuerdo con dotNetManía para la difusión conjunta de su oferta formativa. Leer más...


Disponibles los primeros 28 números de dotNetManía en formato PDF y de libre distribución. Leer más... 

Patrocinadores

Patrocinador Oro
Microsoft

Patrocinadores Plata
Alhambra-Eidos
Solid Quality Mentors

Patrocinadores Bronce
Raona
Plain Concepts
Krasis
ABOX 

 

 

 

Nº 3 Abril 2004 Gestión de concurrencia en ADO.NET Material de apoyo

Por Miguel Katrib y Mario del Valle
 

Entre otras razones .NET supera a tecnologías de componentes precedentes por la transparencia con la que integra código y metadatos favoreciendo con ello la metaprogramación. Este trabajo muestra cómo usando reflexión (reflection) se define un conversor de tipos que permite a partir de un objeto, el cual comparte una misma funcionalidad con un interface, obtener un objeto proxy equivalente en funcionalidad al original pero que garantiza ser subtipo de dicha interface. De este modo el objeto proxy puede ser utilizado como si estáticamente hubiese declarado que implementa el tipo interface. Con ello se facilita la adaptabilidad del software y la factorización de código ya existente para poder aprovechar una funcionalidad común.


Con este artículo mostramos a su vez la potencialidad de la reflexión y de la generación de tipos en tiempo de ejecución. Esta capacidad nos permite
hacer metaprogramación al poder implementar y aplicar patrones, como el ejemplificado para la factorización de tipos, de modo transparente para el programador.

Bibliografía

Visual Basic .NET Reflection Handbook

 

Editorial: Wrox

Autor: James Hart

ISBN: 1-86100-759-0 

Páginas: 300

Precio: 17,49$

Publicación: 2002


 

Más información

Builder.com

Getting .NET class info with Reflection
 

Jason Bock

Investigating Reflection: Documentos y Código fuente

 

Fabio Galupo - msdn

FxCop - Analizador de Buenas Prácticas de programación en .NET


 

Código fuente

void NewMethod(Object x){

...

if (x is B)

      ((B)x).f1();

else if (x is C)

      ((C)x).f1();

...

if (x is B)

      (B)x.fn();

else if (x is C)

      (C)x.fn();

}

 

class IAProxyFor_B : IA

{

       B realTarget;

       public IAProxyFor_B(B x)

       {

          realTarget=x;

       }

       public T1 f1()

       {

          return realTarget.f1();

       }

       ...

       public Tn fn()

       {

          return realTarget.fn();

       }

}

 

void Configure (ComboBox control){

  control.BeginUpdate();

  control.SelectedIndexChanged += new EventHandler(someMethod);

  control.Items.Add(“Default”);

  control.Items.Add(“Auto”);

  control.Text = “Default”;

  control.Sorted = true;

  control.EndUpdate();

}

 

void Configure (ListBox control){

  control.BeginUpdate();

  control.SelectedIndexChanged += new EventHandler(someMethod);

  control.Items.Add(“Default”);

  control.Items.Add(“Auto”);

  control.Text = “Default”;

  control.Sorted = true;

  control.EndUpdate();

}

 

interface IListControl

{

      object SelectedItem{ get; set;}

      int SelectedIndex { get; set; }

      IList Items{ get;}

      string Text {get; set;}

      bool Sorted { get; set; }

      void BeginUpdate();

      void EndUpdate();

      void Refresh();

      event EventHandler SelectedValueChanged;

      event EventHandler SelectedIndexChanged;

}

 

static object castTo(object target, Type interfaceType)

 {

   Type proxyType =

   TypeBuilder proxyTypeBuilder =

     modBuilder.DefineType

      (

       interfaceType.Name

       + “ProxyFor_" + target.GetType().Name,

       TypeAttributes.Class | TypeAttributes.Public,

       typeof (object), //Base type

       new Type[] {interfaceType} //Implemented interface types

      );

    FieldInfo realTarget =

      proxyTypeBuilder.DefineField("realTarget", target.GetType(),

                                   FieldAttributes.Private);

    ConstructorInfo ctor = EmitCtor(proxyTypeBuilder, realTarget);

    EmitMethods(interfaceType, proxyTypeBuilder, realTarget);

    proxyType = proxyTypeBuilder.CreateType();

    return Activator.CreateInstance(proxyType, new object[] {target});

  }

 

class Account{

        private int balance;

        public int Balance

        {

            get{ return balance;}

        }

        //...other methods

}

 

class IATwinOf_B : IA

{

//... The same variables as in B

      //... A constructor to do the copy from b

      //The methods:

      public T1 f1()

      {

            // ... The same IL code as the IL code for f1 in B

      }

      ...

      public T2 fn()

      {

            // ... The same IL code as the IL code for fn in B

      }

}

 

static void EmitMethods(Type interf, TypeBuilder proxyTypeBuilder,

                        FieldInfo realTarget)

 {

   MethodInfo[] methods = interf.GetMethods();

   foreach (MethodInfo mi in methods)

    {

    Type[] argsTypes = getTypesOf(mi.GetParameters());

    MethodBuilder methodBuilder =

       proxyTypeBuilder.DefineMethod(mi.Name,

           MethodAttributes.Public | MethodAttributes.Virtual,

           mi.ReturnType,

           argsTypes);

    MethodInfo realMethod = realTarget.FieldType.GetMethod(mi.Name,

                            argsTypes);

      ILGenerator generator = methodBuilder.GetILGenerator();

    generator.Emit(OpCodes.Ldarg_0);

    generator.Emit(OpCodes.Ldfld, realTarget);

    for (int i = 0; i < argsTypes.Length; i++)

            generator.Emit(OpCodes.Ldarg, i+1);

    OpCode callCode = OpCodes.Call;

    if (realMethod.IsVirtual) callCode = OpCodes.Callvirt;

      generator.EmitCall(callCode, realMethod, null);

      generator.Emit(OpCodes.Ret);

    }

  }

Fuente 1. Generación de cada uno de los métodos del tipo proxy creado por el conversor

 

static bool CheckConformance(Type implementingType, Type interfaceType)

{

      if (!interfaceType.IsInterface)

            throw new ArgumentException("Type parameter must be an

                                         interface type");

      foreach (MethodInfo method in interfaceType.GetMethods())

      {

        bool present = false;

        foreach (MethodInfo implMethod in implementingType.GetMethods())

        {

              if (method.ToString().Equals(implMethod.ToString()))

              {

                    present = truebreak;

              }

        }

        if (!present) return false;

   }

   return true;

}

Fuente 2. Verificación de que un tipo implementa todos los métodos existentes en un tipo interface

 

Volver
 

 

dotNetManía es una revista editada por Netalia. Más información.