/// <summary> /// Create an advice that runs before and after the advised method. /// </summary> /// <param name="linq">Linq</param> /// <param name="advice">Delegate used to produce an expression of code to be invoked instaed of the advised method : Func(Expression = [expression of target instance of advised method call], IEnumerable(Expression) = [enumerable of expression of argument used to call advised method], Expression = [expression of advised method body]) return an expression to invoke instead of the advised method</param> /// <returns>Advice</returns> static public IAdvice Around(this Advisor.ILinq linq, Func <Expression, IEnumerable <Expression>, Expression, Expression> advice) { return(new Advice((_Method, _Pointer) => { var _type = _Method.Type(); var _signature = _Method.Signature(); var _parameters = new Collection <ParameterExpression>(_signature.Select(_Type => Expression.Parameter(_Type)).ToArray()); var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.DeclaringType, true); var _body = _method.GetILGenerator(); _body.Emit(_signature, false); _body.Emit(_Pointer, _type, _signature); _body.Emit(OpCodes.Ret); var _advice = _signature.Instance == null ? advice(null, _parameters, Expression.Call(_method, _parameters)) : advice(_parameters[0], _parameters.Skip(1), Expression.Call(_method, _parameters)); if (_advice == null) { return null; } _method = new DynamicMethod(string.Empty, _type, _signature, _Method.DeclaringType, true); _body = _method.GetILGenerator(); _body.Emit(_signature, false); _body.Emit(OpCodes.Call, Expression.Lambda(_advice, _parameters).CompileToMethod()); _body.Emit(OpCodes.Ret); _method.Prepare(); return _method; })); }
/// <summary> /// Create an advice that runs after the advised method regardless of its outcome. /// </summary> /// <param name="linq">Linq</param> /// <param name="advice">Delegate used to produce an expression of code to be invoked after the advised method : Func(Expression = [expression of target instance of advised method call], IEnumerable(Expression) = [enumerable of expression of argument used to call advised method]) return an expression(void) of code to invoke after the advised method</param> /// <returns>Advice</returns> static public IAdvice After(this Advisor.ILinq linq, Func <Expression, IEnumerable <Expression>, Expression> advice) { return(new Advice((_Method, _Pointer) => { var _signature = _Method.Signature(); var _parameters = new Collection <ParameterExpression>(_signature.Select(_Type => Expression.Parameter(_Type)).ToArray()); var _advice = _signature.Instance == null ? advice(null, _parameters) : advice(_parameters[0], _parameters.Skip(1)); if (_advice == null) { return null; } if (_advice.Type != Metadata.Void) { throw new NotSupportedException(); } var _type = _Method.ReturnType(); var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.DeclaringType, true); var _body = _method.GetILGenerator(); if (_type == Metadata.Void) { _body.BeginExceptionBlock(); _body.Emit(_signature, false); _body.Emit(_Pointer, _type, _signature); _body.BeginFinallyBlock(); _body.Emit(_signature, false); _body.Emit(OpCodes.Call, Expression.Lambda(_advice, _parameters).CompileToMethod()); _body.EndExceptionBlock(); } else { _body.DeclareLocal(_type); _body.BeginExceptionBlock(); _body.Emit(_signature, false); _body.Emit(_Pointer, _type, _signature); _body.Emit(OpCodes.Stloc_0); _body.BeginFinallyBlock(); _body.Emit(_signature, false); _body.Emit(OpCodes.Call, Expression.Lambda(_advice, _parameters).CompileToMethod()); _body.EndExceptionBlock(); _body.Emit(OpCodes.Ldloc_0); } _body.Emit(OpCodes.Ret); _method.Prepare(); return _method; })); }
/// <summary> /// Create an advice that runs after the advised method regardless of its outcome. /// </summary> /// <param name="linq">Linq</param> /// <param name="advice"></param> /// <returns>Advice</returns> static public IAdvice After(this Advisor.ILinq linq, Expression advice) { return(new Advice((_Method, _Pointer) => { var _signature = _Method.Signature(); if (advice == null) { return null; } if (advice.Type != Metadata.Void) { throw new NotSupportedException(); } var _type = _Method.ReturnType(); var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.DeclaringType, true); var _body = _method.GetILGenerator(); if (_type == Metadata.Void) { _body.BeginExceptionBlock(); _body.Emit(_signature, false); _body.Emit(_Pointer, _type, _signature); _body.BeginFinallyBlock(); _body.Emit(OpCodes.Call, Expression.Lambda(advice).CompileToMethod()); _body.EndExceptionBlock(); } else { _body.DeclareLocal(_type); _body.BeginExceptionBlock(); _body.Emit(_signature, false); _body.Emit(_Pointer, _type, _signature); _body.Emit(OpCodes.Stloc_0); _body.BeginFinallyBlock(); _body.Emit(OpCodes.Call, Expression.Lambda(advice).CompileToMethod()); _body.EndExceptionBlock(); _body.Emit(OpCodes.Ldloc_0); } _body.Emit(OpCodes.Ret); _method.Prepare(); return _method; })); }
/// <summary> /// Create an advice that runs before the advised method. /// </summary> /// <param name="linq">Linq</param> /// <param name="advice">Expression of code to be invoked before the advised method</param> /// <returns>Advice</returns> static public IAdvice Before(this Advisor.ILinq linq, Expression advice) { return(new Advice((_Method, _Pointer) => { var _signature = _Method.Signature(); if (advice == null) { return null; } var _type = _Method.ReturnType(); var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.DeclaringType, true); var _body = _method.GetILGenerator(); _body.Emit(OpCodes.Call, Expression.Lambda(advice).CompileToMethod()); _body.Emit(_signature, false); _body.Emit(_Pointer, _type, _signature); _body.Emit(OpCodes.Ret); _method.Prepare(); return _method; })); }
/// <summary> /// After /// </summary> /// <param name="linq">Linq</param> /// <returns>After</returns> static public Advisor.Linq.IAfter After(this Advisor.ILinq linq) { return(null); }