2009-12-25 19 views
14

Quiero aprender el método dinámico y su ejemplo práctico usando C#.
¿Existe alguna relación entre el método dinámico y Reflection?
Por favor, ayúdenme.Ejemplo práctico de método dinámico?

+0

No entiendo el término _método dinámico_. Delphi tiene métodos dinámicos, para los cuales C# no tiene analogía, y hay una técnica de programación llamada _dynamic programming_. ¿O te refieres a _método virtual_? Supongo que, por "Reflación", quiere decir reflexión. –

+3

nadie también hay un concepto de método dinámico en C# – Pankaj

Respuesta

5

Puede crear un método a través de la clase DynamicMethod.

DynamicMethod squareIt = new DynamicMethod(
    "SquareIt", 
    typeof(long), 
    methodArgs, 
    typeof(Example).Module); 

ILGenerator il = squareIt.GetILGenerator(); 
il.Emit(OpCodes.Ldarg_0); 
il.Emit(OpCodes.Conv_I8); 
il.Emit(OpCodes.Dup); 
il.Emit(OpCodes.Mul); 
il.Emit(OpCodes.Ret); 

Fully commented example on MSDN
deben tener en cuenta que el desarrollo de utilizar este método es muy lento y no muy útil.

+0

@VMAtm .. He leído un artículo de DynamicMethod, en algún lugar encontré que son más rápidos que reflection.DynamicMethod también eliminan la necesidad de escribir código personalizado de serialización y deserialización. – Pankaj

+1

Me refiero a la velocidad de desarrollo, no es muy rápido y es muy difícil mantener dicho código. – VMAtm

+0

ILGenerator - es una parte de System.Reflection.Emit En algo es una relación entre Reflection y métodos dinámicos – VMAtm

8

Estamos utilizando métodos dinámicos para acelerar la reflexión. Aquí está el código de nuestro optimizador de reflexión. es sólo el 10% más lenta que la llamada directa y 2000 veces más rápido que la llamada de reflexión

public class ReflectionEmitPropertyAccessor 
    { 
     private readonly bool canRead; 
     private readonly bool canWrite; 
     private IPropertyAccessor emittedPropertyAccessor; 
     private readonly string propertyName; 
     private readonly Type propertyType; 
     private readonly Type targetType; 
     private Dictionary<Type,OpCode> typeOpCodes; 

     public ReflectionEmitPropertyAccessor(Type targetType, string property) 
     { 
      this.targetType = targetType; 
      propertyName = property; 
      var propertyInfo = targetType.GetProperty(property); 
      if (propertyInfo == null) 
      { 
       throw new ReflectionOptimizerException(string.Format("Property \"{0}\" is not found in type "+ "{1}.", property, targetType)); 
      } 
      canRead = propertyInfo.CanRead; 
      canWrite = propertyInfo.CanWrite; 
      propertyType = propertyInfo.PropertyType; 
     } 

     public bool CanRead 
     { 
      get { return canRead; } 
     } 

     public bool CanWrite 
     { 
      get { return canWrite; } 
     } 

     public Type TargetType 
     { 
      get { return targetType; } 
     } 

     public Type PropertyType 
     { 
      get { return propertyType; } 
     } 

     #region IPropertyAccessor Members 

     public object Get(object target) 
     { 
      if (canRead) 
      { 
       if (emittedPropertyAccessor == null) 
       { 
        Init(); 
       } 

       if (emittedPropertyAccessor != null) return emittedPropertyAccessor.Get(target); 

      } 
      else 
      { 
       throw new ReflectionOptimizerException(string.Format("У свойства \"{0}\" нет метода get.", propertyName)); 
      } 
      throw new ReflectionOptimizerException("Fail initialize of " + GetType().FullName); 
     } 

     public void Set(object target, object value) 
     { 
      if (canWrite) 
      { 
       if (emittedPropertyAccessor == null) 
       { 
        Init(); 
       } 
       if (emittedPropertyAccessor != null) emittedPropertyAccessor.Set(target, value); 
      } 
      else 
      { 
       throw new ReflectionOptimizerException(string.Format("Property \"{0}\" does not have method set.", propertyName)); 
      } 
      throw new ReflectionOptimizerException("Fail initialize of " + GetType().FullName); 
     } 

     #endregion 

     private void Init() 
     { 
      InitTypeOpCodes(); 
      var assembly = EmitAssembly(); 
      emittedPropertyAccessor = assembly.CreateInstance("Property") as IPropertyAccessor; 
      if (emittedPropertyAccessor == null) 
      { 
       throw new ReflectionOptimizerException("Shit happense in PropertyAccessor."); 
      } 
     } 

     private void InitTypeOpCodes() 
     { 
      typeOpCodes = new Dictionary<Type, OpCode> 
          { 
           {typeof (sbyte), OpCodes.Ldind_I1}, 
           {typeof (byte), OpCodes.Ldind_U1}, 
           {typeof (char), OpCodes.Ldind_U2}, 
           {typeof (short), OpCodes.Ldind_I2}, 
           {typeof (ushort), OpCodes.Ldind_U2}, 
           {typeof (int), OpCodes.Ldind_I4}, 
           {typeof (uint), OpCodes.Ldind_U4}, 
           {typeof (long), OpCodes.Ldind_I8}, 
           {typeof (ulong), OpCodes.Ldind_I8}, 
           {typeof (bool), OpCodes.Ldind_I1}, 
           {typeof (double), OpCodes.Ldind_R8}, 
           {typeof (float), OpCodes.Ldind_R4} 
          }; 
     } 

     private Assembly EmitAssembly() 
     { 
      var assemblyName = new AssemblyName {Name = "PropertyAccessorAssembly"}; 
      var newAssembly = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); 
      var newModule = newAssembly.DefineDynamicModule("Module"); 
      var dynamicType = newModule.DefineType("Property", TypeAttributes.Public); 
      dynamicType.AddInterfaceImplementation(typeof(IPropertyAccessor)); 
      dynamicType.DefineDefaultConstructor(MethodAttributes.Public); 
      var getParamTypes = new[] { typeof(object) }; 
      var getReturnType = typeof(object); 
      var getMethod = dynamicType.DefineMethod("Get", 
            MethodAttributes.Public | MethodAttributes.Virtual, 
            getReturnType, 
            getParamTypes); 

      var getIL = getMethod.GetILGenerator(); 
      var targetGetMethod = targetType.GetMethod("get_" + propertyName); 

      if (targetGetMethod != null) 
      { 
       getIL.DeclareLocal(typeof(object)); 
       getIL.Emit(OpCodes.Ldarg_1); //Load the first argument 
       getIL.Emit(OpCodes.Castclass, targetType); //Cast to the source type 
       getIL.EmitCall(OpCodes.Call, targetGetMethod, null); //Get the property value 
       if (targetGetMethod.ReturnType.IsValueType) 
       { 
        getIL.Emit(OpCodes.Box, targetGetMethod.ReturnType); //Box 
       } 
       getIL.Emit(OpCodes.Stloc_0); //Store it 
       getIL.Emit(OpCodes.Ldloc_0); 
      } 
      else 
      { 
       getIL.ThrowException(typeof(MissingMethodException)); 
      } 

      getIL.Emit(OpCodes.Ret); 
      var setParamTypes = new[] { typeof(object), typeof(object) }; 
      const Type setReturnType = null; 
      var setMethod = dynamicType.DefineMethod("Set", 
            MethodAttributes.Public | MethodAttributes.Virtual, 
            setReturnType, 
            setParamTypes); 

      var setIL = setMethod.GetILGenerator(); 

      var targetSetMethod = targetType.GetMethod("set_" + propertyName); 
      if (targetSetMethod != null) 
      { 
       Type paramType = targetSetMethod.GetParameters()[0].ParameterType; 

       setIL.DeclareLocal(paramType); 
       setIL.Emit(OpCodes.Ldarg_1); //Load the first argument //(target object) 
       setIL.Emit(OpCodes.Castclass, targetType); //Cast to the source type 
       setIL.Emit(OpCodes.Ldarg_2); //Load the second argument 
       //(value object) 
       if (paramType.IsValueType) 
       { 
        setIL.Emit(OpCodes.Unbox, paramType); //Unbox it  
        if (typeOpCodes.ContainsKey(paramType)) //and load 
        { 
         var load = typeOpCodes[paramType]; 
         setIL.Emit(load); 
        } 
        else 
        { 
         setIL.Emit(OpCodes.Ldobj, paramType); 
        } 
       } 
       else 
       { 
        setIL.Emit(OpCodes.Castclass, paramType); //Cast class 
       } 
       setIL.EmitCall(OpCodes.Callvirt,targetSetMethod, null); //Set the property value 
      } 
      else 
      { 
       setIL.ThrowException(typeof(MissingMethodException)); 
      } 
      setIL.Emit(OpCodes.Ret); 
      // Load the type 
      dynamicType.CreateType(); 
      return newAssembly; 
     } 

    } 

aplicación es agregado de diferentes fuentes y principal es este artículo CodeProject.

+0

Gracias @@ Sergey Miroda ... onw más cosa ¿Hay alguna relación entre el método dinámico y Reflection – Pankaj

+0

Sí lo es. Reflection.Emit es una parte de la reflexión .net. –

+2

también el método dinámico es el __only___método si lo desea en el código de compilación de tiempo de ejecución que puede ser basura recolectada. –

Cuestiones relacionadas