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此处省略好几个字...
原文地址:https://www.cnblogs.com/jroger/p/5238278.html