关于静态代理请参考:
http://www.hechunbo.com/index.php/archives/209.html
动态代理 的特点是程序自动生成代理类,不用再根据业务来一个一个类写了。
是运行时代理。
创建Action特性,标记于方法上
/// <summary>
/// 标记方法特性,在调用类中的方法时,调用before
/// </summary>
public class ActionAttribute : ActionBaseAttribute
{
public override void Before(string @method, object[] parameters)
{
Console.WriteLine("ActionAttribute before,method:" + method);
}
public override object After(string @method, object result)
{
Console.WriteLine(" ActionAttribute after,method:" + method);
return base.After(method, result);
}
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class ActionBaseAttribute : Attribute
{
public virtual void Before(string @method, object[] parameters) { }
public virtual object After(string @method, object result) { return result; }
}
创建Interceptor特性,标记于类
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class InterceptorBaseAttribute : Attribute
{
public virtual object Invoke(object @object, string @method, object[] parameters)
{
return @object.GetType().GetMethod(@method).Invoke(@object, parameters);
}
}
/// <summary>
/// 定义类的特性。也是在方法前后调用 ,但是先办理出action日志 。因为action特性标记在方法上。
/// </summary>
public class InterceptorAttribute : InterceptorBaseAttribute
{
public override object Invoke(object @object, string @method, object[] parameters)
{
Console.WriteLine("InterceptorAttribute before invokc");
object obj = null;
try
{
obj = base.Invoke(@object, method, parameters);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine("InterceptorAttribute after invoke");
return obj;
}
}
public interface IBusinessClass
{
void add();
}
业务类和业务接口
public interface IBusinessClass
{
void add();
}
[Interceptor]
public class Business : IBusinessClass
{
[Action]
public void add()
{
Console.WriteLine("add method");
}
}
用Emit生成的动态代理类的IL
public class DynamicProxy
{
public static TInterface CreateProxyOfRealize<TInterface, TImp>()
where TImp : class, new()
where TInterface : class
{
return Invoke<TInterface, TImp>();
}
public static TProxyClass CreateProxyOfInherit<TProxyClass>() where TProxyClass : class, new()
{
return Invoke<TProxyClass, TProxyClass>(true);
}
private static TInterface Invoke<TInterface, TImp>(bool inheritMode = false)
where TImp : class, new()
where TInterface : class
{
var impType = typeof (TImp);
string nameOfAssembly = impType.Name + "ProxyAssembly";
string nameOfModule = impType.Name + "ProxyModule";
string nameOfType = impType.Name + "Proxy";
var assemblyName = new AssemblyName(nameOfAssembly);
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var moduleBuilder = assembly.DefineDynamicModule(nameOfModule);
//var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
//var moduleBuilder = assembly.DefineDynamicModule(nameOfModule, nameOfAssembly + ".dll");
TypeBuilder typeBuilder;
if (inheritMode)
typeBuilder = moduleBuilder.DefineType(nameOfType, TypeAttributes.Public, impType);
else
typeBuilder = moduleBuilder.DefineType(nameOfType, TypeAttributes.Public, null,
new[] {typeof (TInterface)});
InjectInterceptor<TImp>(typeBuilder, impType.GetCustomAttribute(typeof (InterceptorBaseAttribute)).GetType(),inheritMode);
var t = typeBuilder.CreateType();
//assembly.Save(nameOfAssembly + ".dll");
return Activator.CreateInstance(t) as TInterface;
}
private static void InjectInterceptor<TImp>(TypeBuilder typeBuilder, Type interceptorAttributeType,bool inheritMode = false)
{
var impType = typeof (TImp);
// ---- define fields ----
FieldBuilder fieldInterceptor = null;
if (interceptorAttributeType != null)
{
fieldInterceptor = typeBuilder.DefineField("_interceptor", interceptorAttributeType,
FieldAttributes.Private);
}
// ---- define costructors ----
if (interceptorAttributeType != null)
{
var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public,
CallingConventions.Standard, null);
var ilOfCtor = constructorBuilder.GetILGenerator();
ilOfCtor.Emit(OpCodes.Ldarg_0);
ilOfCtor.Emit(OpCodes.Newobj, interceptorAttributeType.GetConstructor(new Type[0]));
ilOfCtor.Emit(OpCodes.Stfld, fieldInterceptor);
ilOfCtor.Emit(OpCodes.Ret);
}
// ---- define methods ----
var methodsOfType = impType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
string[] ignoreMethodName = new[] {"GetType", "ToString", "GetHashCode", "Equals"};
foreach (var method in methodsOfType)
{
//ignore method
if (ignoreMethodName.Contains(method.Name))
return;
var methodParameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray();
MethodAttributes methodAttributes;
if (inheritMode)
methodAttributes = MethodAttributes.Public | MethodAttributes.Virtual;
else
methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot |
MethodAttributes.Virtual | MethodAttributes.Final;
var methodBuilder = typeBuilder.DefineMethod(method.Name, methodAttributes, CallingConventions.Standard,
method.ReturnType, methodParameterTypes);
var ilMethod = methodBuilder.GetILGenerator();
// set local field
var impObj = ilMethod.DeclareLocal(impType); //instance of imp object
var methodName = ilMethod.DeclareLocal(typeof (string)); //instance of method name
var parameters = ilMethod.DeclareLocal(typeof (object[])); //instance of parameters
var result = ilMethod.DeclareLocal(typeof (object)); //instance of result
LocalBuilder actionAttributeObj = null;
//attribute init
Type actionAttributeType = null;
if (method.GetCustomAttribute(typeof (ActionBaseAttribute)) != null ||
impType.GetCustomAttribute(typeof (ActionBaseAttribute)) != null)
{
//method can override class attrubute
if (method.GetCustomAttribute(typeof (ActionBaseAttribute)) != null)
{
actionAttributeType = method.GetCustomAttribute(typeof (ActionBaseAttribute)).GetType();
}
else if (impType.GetCustomAttribute(typeof (ActionBaseAttribute)) != null)
{
actionAttributeType = impType.GetCustomAttribute(typeof (ActionBaseAttribute)).GetType();
}
actionAttributeObj = ilMethod.DeclareLocal(actionAttributeType);
ilMethod.Emit(OpCodes.Newobj, actionAttributeType.GetConstructor(new Type[0]));
ilMethod.Emit(OpCodes.Stloc, actionAttributeObj);
}
//instance imp
ilMethod.Emit(OpCodes.Newobj, impType.GetConstructor(new Type[0]));
ilMethod.Emit(OpCodes.Stloc, impObj);
//if no attribute
if (fieldInterceptor != null || actionAttributeObj != null)
{
ilMethod.Emit(OpCodes.Ldstr, method.Name);
ilMethod.Emit(OpCodes.Stloc, methodName);
ilMethod.Emit(OpCodes.Ldc_I4, methodParameterTypes.Length);
ilMethod.Emit(OpCodes.Newarr, typeof (object));
ilMethod.Emit(OpCodes.Stloc, parameters);
// build the method parameters
for (var j = 0; j < methodParameterTypes.Length; j++)
{
ilMethod.Emit(OpCodes.Ldloc, parameters);
ilMethod.Emit(OpCodes.Ldc_I4, j);
ilMethod.Emit(OpCodes.Ldarg, j + 1);
//box
ilMethod.Emit(OpCodes.Box, methodParameterTypes[j]);
ilMethod.Emit(OpCodes.Stelem_Ref);
}
}
//如果存在action特性,加载实例化对象,参数,执行before方法
//dynamic proxy action before
if (actionAttributeType != null)
{
//load arguments
ilMethod.Emit(OpCodes.Ldloc, actionAttributeObj);
ilMethod.Emit(OpCodes.Ldloc, methodName);
ilMethod.Emit(OpCodes.Ldloc, parameters);
ilMethod.Emit(OpCodes.Call, actionAttributeType.GetMethod("Before"));
}
//如果存在interceptor特性,调用类字段的invoke方法
if (interceptorAttributeType != null)
{
//load arguments
ilMethod.Emit(OpCodes.Ldarg_0); //this
ilMethod.Emit(OpCodes.Ldfld, fieldInterceptor);
ilMethod.Emit(OpCodes.Ldloc, impObj);
ilMethod.Emit(OpCodes.Ldloc, methodName);
ilMethod.Emit(OpCodes.Ldloc, parameters);
// call Invoke() method of Interceptor
ilMethod.Emit(OpCodes.Callvirt, interceptorAttributeType.GetMethod("Invoke"));
}
else
{
//direct call method
if (method.ReturnType == typeof (void) && actionAttributeType == null)
{
ilMethod.Emit(OpCodes.Ldnull);
}
ilMethod.Emit(OpCodes.Ldloc, impObj);
for (var j = 0; j < methodParameterTypes.Length; j++)
{
ilMethod.Emit(OpCodes.Ldarg, j + 1);
}
ilMethod.Emit(OpCodes.Callvirt, impType.GetMethod(method.Name));
//box
if (actionAttributeType != null)
{
if (method.ReturnType != typeof (void))
ilMethod.Emit(OpCodes.Box, method.ReturnType);
else
ilMethod.Emit(OpCodes.Ldnull);
}
}
//如果action特性存在,则把结果包装成object传给after方法
//dynamic proxy action after
if (actionAttributeType != null)
{
ilMethod.Emit(OpCodes.Stloc, result);
//load arguments
ilMethod.Emit(OpCodes.Ldloc, actionAttributeObj);
ilMethod.Emit(OpCodes.Ldloc, methodName);
ilMethod.Emit(OpCodes.Ldloc, result);
ilMethod.Emit(OpCodes.Call, actionAttributeType.GetMethod("After"));
}
// pop the stack if return void //void类型,直接返回结果
if (method.ReturnType == typeof (void))
{
ilMethod.Emit(OpCodes.Pop);
}
else
{
//unbox,if direct invoke,no box
if (fieldInterceptor != null || actionAttributeObj != null)
{
if (method.ReturnType.IsValueType)//值类型=拆箱
ilMethod.Emit(OpCodes.Unbox_Any, method.ReturnType);
else
ilMethod.Emit(OpCodes.Castclass, method.ReturnType); //引用类型,则需要类型转换
}
}
// complete
ilMethod.Emit(OpCodes.Ret);
}
}
}
方法测试和调用
class Program
{
static void Main(string[] args)
{
IBusinessClass instance = DynamicProxy.CreateProxyOfRealize<IBusinessClass, Business>();
instance.add();
Console.ReadKey();
}
}
方法运行结果
先输出action类的before方法 ,再调用Interceptor特性的before方法 。出是先interceptor,后action
==>action方法特性在最外层, Intercepror特性类在最方法的最内层。
ActionAttribute before,method:add
InterceptorAttribute before invokc
add method
InterceptorAttribute after invoke
ActionAttribute after,method:add
参考
AOP从静态代理到动态代理(Emit实现)详解
还不快抢沙发