参考链接:
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";