正文
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[];
} 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 = ; 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 >
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(, 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 = "";