zoukankan      html  css  js  c++  java
  • MSIL Emit AOP

    参考链接:

    https://pieterderycke.wordpress.com/tag/reflection-emit/

    http://www.moon-soft.com/doc/23252.htm

    http://www.codeproject.com/Articles/18677/Dynamic-Assemblies-using-Reflection-Emit-Part-II-o

    示例一:

      public interface IProxy
      {
          void GetProxyInstance();
      }
    
      public static class Util
      {
          public static void Before(string message)
          {
              Console.WriteLine( $"dynamic message: {message}" );
          }
      }
    
      public class TypeCreator
      {
          private readonly Type _targetType;
    
          public TypeCreator(Type targetType)
          {
              this._targetType = targetType;
          }
    
          public Type Build()
          {
              var currentAppDomain = AppDomain.CurrentDomain;
              var assemblyName = new AssemblyName {
                  Name = "_Aop_Assembly_" + this._targetType.Name
              };
              var assemblyBuilder = currentAppDomain.DefineDynamicAssembly( assemblyName, AssemblyBuilderAccess.Run );
              var moduleBuilder = assemblyBuilder.DefineDynamicModule( "_Aop_Module_" + this._targetType.Name );
              var implTypeName = "_Impl_" + this._targetType.Name;
              var implTypeAttribute = TypeAttributes.Class | TypeAttributes.Public;
              Type implTypeParent;
              Type[] implTypeInterfaces;
    
              if( this._targetType.IsInterface )
              {
                  implTypeParent = null;
                  implTypeInterfaces = new[] {
                      this._targetType
                  };
              }
              else
              {
                  implTypeParent = this._targetType;
                  implTypeInterfaces = new Type[0];
              }
    
              var typeBuilder = moduleBuilder.DefineType( implTypeName, implTypeAttribute, implTypeParent, implTypeInterfaces );
              var implTargetMethods = this._targetType.GetMethods();
    
              foreach( var implTargetMethod in implTargetMethods )
              {
                  if( implTargetMethod.IsVirtual )
                  {
                      var parameters = implTargetMethod.GetParameters();
                      var parameterTypes = new Type[parameters.Length];
    
                      for( var i = 0; i < parameters.Length; i++ )
                      {
                          parameterTypes[i] = parameters[i].ParameterType;
                      }
    
                      var methodBuilder = typeBuilder.DefineMethod( implTargetMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, implTargetMethod.ReturnType, parameterTypes );
    
                      var ilGen = methodBuilder.GetILGenerator();
    
                      ilGen.Emit( OpCodes.Ldstr, "Before Execute " + this._targetType.Name + ";" );
                      ilGen.Emit( OpCodes.Call, typeof( Util ).GetMethod( "Before", new Type[] {
                          typeof( string )
                      } ) );
                      ilGen.Emit( OpCodes.Ret );
                  }
              }
    
              return typeBuilder.CreateType();
          }
      }
    
      // 调用示例:
      var tc = new TypeCreator( typeof( IProxy ) );
      var dynamicType = tc.Build();
      var proxy = (IProxy) Activator.CreateInstance( dynamicType );
    
      proxy.GetProxyInstance();

    示例二:

      public class ViewModelBase
      {
          protected void RaisePropertyChanged( string propertyName )
          {
              Console.WriteLine( $"PropertyName: {propertyName}" );
          }
      }
    
      [AttributeUsage(AttributeTargets.Property)]
      public class RaisePropertyChangedAttribute : Attribute
      {
    
      }
    
      public class SampleViewModel : ViewModelBase
      {
          [RaisePropertyChanged]
          public virtual string SomeProperty { get; set; }
      }
    
      public static class ReflectionEmitViewModelFactory
      {
          public static T CreateInstance<T>()
              where T : ViewModelBase
          {
              Type vmType = typeof(T);
    
              VerifyViewModelType(vmType);
    
              // Create everything required to get a module builder
              AssemblyName assemblyName = new AssemblyName("SmartViewModelDynamicAssembly");
              AppDomain domain = AppDomain.CurrentDomain;
              AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
              //AssemblyBuilderAccess.RunAndSave);
              ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name);
    
              string dynamicTypeName = Assembly.CreateQualifiedName(vmType.AssemblyQualifiedName, "Smart" + vmType.Name);
    
              TypeBuilder typeBuilder = moduleBuilder.DefineType(dynamicTypeName,
                  TypeAttributes.Public | TypeAttributes.Class, vmType);
    
              MethodInfo raisePropertyChangedMethod = typeof(ViewModelBase).GetMethod("RaisePropertyChanged",
                  BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string) }, null);
    
              foreach( PropertyInfo propertyInfo in FindNotifyPropertyChangCandidates<T>() )
                  UpdateProperty(propertyInfo, typeBuilder, raisePropertyChangedMethod);
    
              Type dynamicType = typeBuilder.CreateType();
    
              return (T)Activator.CreateInstance(dynamicType);
          }
    
          private static void VerifyViewModelType( Type vmType )
          {
              if( vmType.IsSealed )
                  throw new InvalidOperationException("The specified view model type is not allowed to be sealed.");
          }
    
          private static IEnumerable<PropertyInfo> FindNotifyPropertyChangCandidates<T>()
          {
              return from p in typeof(T).GetProperties()
                     where p.GetSetMethod() != null && p.GetSetMethod().IsVirtual &&
                     p.GetCustomAttributes(typeof(RaisePropertyChangedAttribute), false).Length > 0
                     select p;
          }
    
          private static void UpdateProperty( PropertyInfo propertyInfo, TypeBuilder typeBuilder,
              MethodInfo raisePropertyChangedMethod )
          {
              // Update the setter of the class
              PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyInfo.Name,
                  PropertyAttributes.None, propertyInfo.PropertyType, null);
    
              // Create set method
              MethodBuilder builder = typeBuilder.DefineMethod("set_" + propertyInfo.Name,
                  MethodAttributes.Public | MethodAttributes.Virtual, null, new Type[] { propertyInfo.PropertyType });
              builder.DefineParameter(1, ParameterAttributes.None, "value");
              ILGenerator generator = builder.GetILGenerator();
    
              // Add IL code for set method
              generator.Emit(OpCodes.Nop);
              generator.Emit(OpCodes.Ldarg_0);
              generator.Emit(OpCodes.Ldarg_1);
              generator.Emit(OpCodes.Call, propertyInfo.GetSetMethod());
    
              // Call property changed for object
              generator.Emit(OpCodes.Nop);
              generator.Emit(OpCodes.Ldarg_0);
              generator.Emit(OpCodes.Ldstr, propertyInfo.Name);
              generator.Emit(OpCodes.Callvirt, raisePropertyChangedMethod);
              generator.Emit(OpCodes.Nop);
              generator.Emit(OpCodes.Ret);
              propertyBuilder.SetSetMethod(builder);
          }
      }
    
      //调用示例:
      SampleViewModel viewModel = ReflectionEmitViewModelFactory.CreateInstance<SampleViewModel>();
      viewModel.SomeProperty = "10";
    本博客内容,如需转载请务必保留超链接。

    Contact Me:Mail此处省略好几个字...
  • 相关阅读:
    构建之法阅读笔记01
    软件工程个人作业01
    第一个PSP0级
    java实现课表的增加
    软件工程概论01
    异常处理
    流与文件课件课后作业1计算容量
    第九周课堂测试
    第八周动手动脑
    JAVA项目中常用的异常知识点总结
  • 原文地址:https://www.cnblogs.com/jroger/p/5238278.html
Copyright © 2011-2022 走看看