/// <summary> /// Create an advice that runs after the advised method only if it exits by throwing an exception. /// </summary> /// <param name="basic">Basic</param> /// <param name="advice">Delegate to be invoked after the advised method : Action(object = [target instance of advised method call], object[] = [boxed arguments used to call advised method], Exception = [exception thrown])</param> /// <returns>Advice</returns> static public Advice Throwing(this Advice.Style.Basic.IAfter basic, Action <object, object[], Exception> advice) { return(new Advice((_Method, _Pointer, _Boundary) => { if (_Boundary != null) { return new Advice.Boundary.Sequence.Factory(_Boundary, new Advice.Boundary.Advanced.After.Throwing.Singleton(_Method, advice)); } var _signature = _Method.Signature(); var _type = _Method.ReturnType(); var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.Module, true); var _body = _method.GetILGenerator(); _body.DeclareLocal(Metadata <Exception> .Type); if (_type == Runtime.Void) { _body.BeginExceptionBlock(); _body.Emit(_signature, false); _body.Emit(_Pointer, _type, _signature); _body.BeginCatchBlock(Metadata <Exception> .Type); _body.Emit(OpCodes.Stloc_0); if (advice.Target != null) { _body.Emit(OpCodes.Ldsfld, Advice.Module.DefineField(advice.Target)); } _body.Emit(_signature, true); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Call, advice.Method); _body.Emit(OpCodes.Rethrow); _body.EndExceptionBlock(); } else { _body.DeclareLocal(_type); _body.BeginExceptionBlock(); _body.Emit(_signature, false); _body.Emit(_Pointer, _type, _signature); _body.Emit(OpCodes.Stloc_1); _body.BeginCatchBlock(Metadata <Exception> .Type); _body.Emit(OpCodes.Stloc_0); if (advice.Target != null) { _body.Emit(OpCodes.Ldsfld, Advice.Module.DefineField(advice.Target)); } _body.Emit(_signature, true); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Call, advice.Method); _body.Emit(OpCodes.Rethrow); _body.EndExceptionBlock(); _body.Emit(OpCodes.Ldloc_1); } _body.Emit(OpCodes.Ret); _method.Prepare(); return _method; })); }
/// <summary> /// Create an advice that runs after the advised method only if it completes successfully. /// </summary> /// <param name="basic">Basic</param> /// <param name="advice">Delegate to be invoked after the advised method : Action(object = [target instance of advised method call], object[] = [boxed arguments used to call advised method], object = [return value (null if return type is void)])</param> /// <returns>Advice</returns> static public Advice Returning(this Advice.Style.Basic.IAfter basic, Action <object, object[], object> advice) { return(new Advice((_Method, _Pointer, _Boundary) => { if (_Boundary != null) { return _Boundary.Combine(new Advice.Boundary.Advanced.After.Returning.Singleton(_Method, advice)); } var _signature = _Method.Signature(); var _type = _Method.ReturnType(); var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.Module, true); var _body = _method.GetILGenerator(); _body.DeclareLocal(Metadata <object> .Type); _body.Emit(_signature, false); _body.Emit(_Pointer, _type, _signature); if (_type == Runtime.Void) { _body.Emit(OpCodes.Ldnull); } else { _body.Emit(OpCodes.Dup); if (_type.IsValueType) { _body.Emit(OpCodes.Box, _type); } else if (_type != Metadata <object> .Type) { _body.Emit(OpCodes.Castclass, Metadata <object> .Type); } } _body.Emit(OpCodes.Stloc_0); if (advice.Target != null) { _body.Emit(OpCodes.Ldsfld, Advice.Module.DefineField(advice.Target)); } _body.Emit(_signature, true); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Call, advice.Method); _body.Emit(OpCodes.Ret); _method.Prepare(); return _method; })); }
/// <summary> /// Create an advice that runs after the advised method only if it completes successfully. /// </summary> /// <param name="basic">Basic</param> /// <param name="advice">Delegate to be invoked after the advised method</param> /// <returns>Advice</returns> static public Advice Returning(this Advice.Style.Basic.IAfter basic, Action advice) { return(new Advice((_Method, _Pointer, _Boundary) => { if (_Boundary != null) { return _Boundary.Combine(new Advice.Boundary.Basic.After.Returning.Singleton(advice)); } var _type = _Method.ReturnType(); var _signature = _Method.Signature(); var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.Module, true); var _body = _method.GetILGenerator(); _body.Emit(_signature, false); _body.Emit(_Pointer, _type, _signature); if (advice.Target != null) { _body.Emit(OpCodes.Ldsfld, Advice.Module.DefineField(advice.Target)); } _body.Emit(OpCodes.Call, advice.Method); _body.Emit(OpCodes.Ret); _method.Prepare(); return _method; })); }