Пример #1
0
 /// <summary>
 /// Create an advice that runs before the advised method.
 /// </summary>
 /// <param name="reflection">Reflection</param>
 /// <param name="advice">Delegate used to emit code to be invoked before the advised method</param>
 /// <returns>Advice</returns>
 static public Advice Before(this Advice.Style.IReflection reflection, Action <ILGenerator> advice)
 {
     return(new Advice((_Method, _Pointer, _Boundary) =>
     {
         var _signature = _Method.Signature();
         var _type = _Method.ReturnType();
         var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.Module, true);
         var _body = _method.GetILGenerator();
         if (_Boundary != null) //TODO dynamic implementation of boundary will avoid redirection overhead.
         {
             _body.Emit(advice);
             _body.Emit(OpCodes.Ret);
             _method.Prepare();
             var _action = new DynamicMethod(string.Empty, Runtime.Void, new Type[] { Metadata <object> .Type, Metadata <object> .Type, Metadata <object[]> .Type }, true);
             var _redirection = _action.GetILGenerator();
             if (_signature.Instance != null)
             {
                 _redirection.Emit(OpCodes.Ldarg_1);
                 if (_signature.Instance.IsValueType)
                 {
                     _redirection.Emit(OpCodes.Unbox_Any, _signature.Instance);
                 }
                 else
                 {
                     _redirection.Emit(OpCodes.Castclass, _signature.Instance);
                 }
             }
             for (var _index = 0; _index < _signature.Length; _index++)
             {
                 var _parameter = _signature[_index];
                 _redirection.Emit(OpCodes.Ldarg_2);
                 _redirection.Emit(OpCodes.Ldc_I4, _index); //TODO shortcut
                 _redirection.Emit(OpCodes.Ldelem_Ref);
                 if (_parameter.IsValueType)
                 {
                     _redirection.Emit(OpCodes.Unbox_Any, _parameter);
                 }
                 else
                 {
                     _redirection.Emit(OpCodes.Castclass, _parameter);
                 }
             }
             _redirection.Emit(OpCodes.Call, _method);
             _redirection.Emit(OpCodes.Ret);
             _action.Prepare();
             return _Boundary.Combine(new Advice.Boundary.Advanced.Before.Singleton(_Method, _action.CreateDelegate(Metadata <Action <object, object[]> > .Type, null) as Action <object, object[]>));
         }
         else
         {
             _body.Emit(advice);
             _body.Emit(_signature, false);
             _body.Emit(_Pointer, _type, _signature);
             _body.Emit(OpCodes.Ret);
             _method.Prepare();
             return _method;
         }
     }));
 }
Пример #2
0
 /// <summary>
 /// Create an advice that runs after the advised method regardless of its outcome.
 /// </summary>
 /// <param name="reflection">Reflection</param>
 /// <param name="advice">Delegate used to emit code to be invoked after the advised method</param>
 /// <returns>Advice</returns>
 static public IAdvice After(this Advisor.IReflection reflection, Action <ILGenerator> advice)
 {
     return(new Advice((_Method, _Pointer) =>
     {
         var _type = _Method.Type();
         var _signature = _Method.Signature();
         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(advice);
             _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(advice);
             _body.EndExceptionBlock();
             _body.Emit(OpCodes.Ldloc_0);
         }
         _body.Emit(OpCodes.Ret);
         _method.Prepare();
         return _method;
     }));
 }
Пример #3
0
 /// <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 only if it completes successfully.
 /// </summary>
 /// <param name="linq">Linq</param>
 /// <param name="advice">Expression (void) of code to be invoked after the advised method</param>
 /// <returns>Advice</returns>
 static public Advice Returning(this Advice.Style.Linq.IAfter linq, Expression advice)
 {
     return(new Advice((_Method, _Pointer, _Boundary) =>
     {
         if (_Boundary != null)
         {
             return _Boundary.Combine(new Advice.Boundary.Basic.After.Returning.Singleton(Expression.Lambda <Action>(advice).Compile()));
         }
         var _signature = _Method.Signature();
         if (advice == null)
         {
             return null;
         }
         if (advice.Type != Runtime.Void)
         {
             throw new NotSupportedException();
         }
         var _type = _Method.ReturnType();
         var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.Module, true);
         var _body = _method.GetILGenerator();
         _body.Emit(_signature, false);
         _body.Emit(_Pointer, _type, _signature);
         _body.Emit(OpCodes.Call, Expression.Lambda(advice).CompileToMethod());
         _body.Emit(OpCodes.Ret);
         _method.Prepare();
         return _method;
     }));
 }
Пример #5
0
        private IntPtr Override(MethodBase method, IntPtr pointer)
        {
            var _type       = method.ReturnType();
            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 _invocation = _signature.Instance == null?this.Override(method, null, _parameters, Expression.Call(_method, _parameters)) : this.Override(method, _parameters[0], _parameters.Skip(1), Expression.Call(_method, _parameters));

            if (_invocation == null)
            {
                return(pointer);
            }
            _method = new DynamicMethod(string.Empty, _type, _signature, method.DeclaringType, true);
            _body   = _method.GetILGenerator();
            _body.Emit(_signature, false);
            _body.Emit(OpCodes.Call, Expression.Lambda(_invocation, _parameters).CompileToMethod());
            _body.Emit(OpCodes.Ret);
            _method.Prepare();
            return(_method.GetFunctionPointer());
        }
Пример #6
0
 /// <summary>
 /// Create an advice that runs before the advised method.
 /// </summary>
 /// <param name="basic">Basic</param>
 /// <param name="advice">Delegate to be invoked before the advised method : Action(object = [target instance of advised method call], object[] = [boxed arguments used to call advised method])</param>
 /// <returns>Advice</returns>
 static public Advice Before(this Advice.Style.IBasic basic, Action <object, object[]> advice)
 {
     return(new Advice((_Method, _Pointer, _Boundary) =>
     {
         if (_Boundary != null)
         {
             return _Boundary.Combine(new Advice.Boundary.Advanced.Before.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();
         if (advice.Target != null)
         {
             _body.Emit(OpCodes.Ldsfld, Advice.Module.DefineField(advice.Target));
         }
         _body.Emit(_signature, true);
         _body.Emit(OpCodes.Call, advice.Method);
         _body.Emit(_signature, false);
         _body.Emit(_Pointer, _type, _signature);
         _body.Emit(OpCodes.Ret);
         _method.Prepare();
         return _method;
     }));
 }
Пример #7
0
 /// <summary>
 /// Create an advice that runs before the advised method.
 /// </summary>
 /// <param name="basic">Basic</param>
 /// <param name="advice">Delegate to be invoked before the advised method</param>
 /// <returns>Advice</returns>
 static public Advice Before(this Advice.Style.IBasic basic, Action advice)
 {
     //TODO : test if asynchronous! if true, emit Boundary inheritor => if advice.Target == null && method is public => call directly method, other else, stora delegate as field and call it in before method.
     return(new Advice((_Method, _Pointer, _Boundary) =>
     {
         if (_Boundary != null)
         {
             return _Boundary.Combine(new Advice.Boundary.Basic.Before.Singleton(advice));
         }
         var _signature = _Method.Signature();
         var _type = _Method.ReturnType();
         var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.Module, true);
         var _body = _method.GetILGenerator();
         if (advice.Target != null)
         {
             _body.Emit(OpCodes.Ldsfld, Advice.Module.DefineField(advice.Target));
         }
         _body.Emit(OpCodes.Call, advice.Method);
         _body.Emit(_signature, false);
         _body.Emit(_Pointer, _type, _signature);
         _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="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 Returning(this Advisor.Linq.IAfter linq, Func <Expression, IEnumerable <Expression>, Expression> advice)
 {
     return(new Advice((_Method, _Pointer) =>
     {
         var _signature = _Method.Signature();
         var _parameters = _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 _Method;
         }
         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();
         _body.Emit(_signature, false);
         _body.Emit(_Pointer, _Method.ReturnType, _signature);
         _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 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;
     }));
 }
Пример #10
0
                static private MethodInfo Method(MethodBase method, IntPtr pointer)
                {
                    var _type      = method.Type();
                    var _signature = method.Signature();
                    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);
                    _method.Prepare();
                    return(_method);
                }
Пример #11
0
 /// <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 IAdvice Throwing(this Advisor.Basic.IAfter basic, Action <object, object[], Exception> advice)
 {
     return(new Advice((_Method, _Pointer) =>
     {
         var _signature = _Method.Signature();
         var _type = _Method.Type();
         var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.DeclaringType, true);
         var _body = _method.GetILGenerator();
         _body.DeclareLocal(Metadata <Exception> .Type);
         if (_type == Metadata.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, Advisor.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, Advisor.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;
     }));
 }
Пример #12
0
 /// <summary>
 /// Create an advice that runs after the advised method only if it exits by throwing an exception.
 /// </summary>
 /// <param name="linq">Linq</param>
 /// <param name="advice">Expression (void) of code to invoke after the advised method</param>
 /// <returns>Advice</returns>
 static public Advice Throwing(this Advice.Style.Linq.IAfter linq, Expression advice)
 {
     return(new Advice((_Method, _Pointer, _Boundary) =>
     {
         if (_Boundary != null)
         {
             return _Boundary.Combine(new Advice.Boundary.Basic.After.Throwing.Singleton(Expression.Lambda <Action>(advice).Compile()));
         }
         var _signature = _Method.Signature();
         var _exception = Expression.Parameter(Metadata <Exception> .Type);
         if (advice == null)
         {
             return null;
         }
         if (advice.Type != Runtime.Void)
         {
             throw new NotSupportedException();
         }
         var _type = _Method.ReturnType();
         var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.Module, true);
         var _body = _method.GetILGenerator();
         if (_type == Runtime.Void)
         {
             _body.BeginExceptionBlock();
             _body.Emit(_signature, false);
             _body.Emit(_Pointer, _type, _signature);
             _body.BeginCatchBlock(Metadata <Exception> .Type);
             _body.Emit(OpCodes.Pop);
             _body.Emit(OpCodes.Call, Expression.Lambda(advice).CompileToMethod());
             _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_0);
             _body.BeginCatchBlock(Metadata <Exception> .Type);
             _body.Emit(OpCodes.Pop);
             _body.Emit(OpCodes.Call, Expression.Lambda(advice).CompileToMethod());
             _body.Emit(OpCodes.Rethrow);
             _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 only if it exits by throwing an exception.
 /// </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 Throwing(this Advisor.Linq.IAfter 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 _exception = Expression.Parameter(Metadata <Exception> .Type);
         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.Type();
         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.BeginCatchBlock(Metadata <Exception> .Type);
             _body.Emit(OpCodes.Pop);
             _body.Emit(_signature, false);
             _body.Emit(OpCodes.Call, Expression.Lambda(_advice, _parameters).CompileToMethod());
             _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_0);
             _body.BeginCatchBlock(Metadata <Exception> .Type);
             _body.Emit(OpCodes.Pop);
             _body.Emit(_signature, false);
             _body.Emit(OpCodes.Call, Expression.Lambda(_advice, _parameters).CompileToMethod());
             _body.Emit(OpCodes.Rethrow);
             _body.EndExceptionBlock();
             _body.Emit(OpCodes.Ldloc_0);
         }
         _body.Emit(OpCodes.Ret);
         _method.Prepare();
         return _method;
     }));
 }
Пример #14
0
 /// <summary>
 /// Create an advice that runs before the advised method.
 /// </summary>
 /// <param name="linq">Linq</param>
 /// <param name="advice">Delegate used to produce an expression of code to be invoked before 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 before the advised method</param>
 /// <returns>Advice</returns>
 static public Advice Before(this Advice.Style.ILinq linq, Func <Expression, IEnumerable <Expression>, Expression> advice)
 {
     return(new Advice((_Method, _Pointer, _Boundary) =>
     {
         if (advice == null)
         {
             return null;
         }
         var _signature = _Method.Signature();
         if (_Boundary != null)
         {
             //TODO dynamic implementation will be faster by avoiding boxing/casting
             var _instance = Expression.Parameter(Metadata <object> .Type);
             var _arguments = Expression.Parameter(Metadata <object[]> .Type);
             var _advice = advice(_signature.Instance == null ? null : _signature.Instance.IsValueType ? Expression.Convert(_instance, _signature.Instance) : Expression.TypeAs(_instance, _signature.Instance), new Collection <Expression>(_signature.Parameters.Select((_Parameter, _Index) => _Parameter.IsValueType ? Expression.Convert(Expression.ArrayIndex(_arguments, Expression.Constant(_Index, Metadata <int> .Type)), _Parameter) : Expression.TypeAs(Expression.ArrayIndex(_arguments, Expression.Constant(_Index, Metadata <int> .Type)), _Parameter)).ToArray()));
             if (_advice == null)
             {
                 return null;
             }
             if (_advice.Type != Runtime.Void)
             {
                 throw new NotSupportedException();
             }
             return _Boundary.Combine(new Advice.Boundary.Advanced.Before.Singleton(_Method, Expression.Lambda <Action <object, object[]> >(_advice, _instance, _arguments).Compile()));
         }
         else
         {
             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 != Runtime.Void)
             {
                 throw new NotSupportedException();
             }
             var _type = _Method.ReturnType();
             var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.Module, true);
             var _body = _method.GetILGenerator();
             _body.Emit(_signature, false);
             _body.Emit(OpCodes.Call, Expression.Lambda(_advice, _parameters).CompileToMethod());
             _body.Emit(_signature, false);
             _body.Emit(_Pointer, _type, _signature);
             _body.Emit(OpCodes.Ret);
             _method.Prepare();
             return _method;
         }
     }));
 }
Пример #15
0
 /// <summary>
 /// Create an advice that runs before the advised method.
 /// </summary>
 /// <param name="reflection">Reflection</param>
 /// <param name="advice">Delegate used to emit code to be invoked before the advised method</param>
 /// <returns>Advice</returns>
 static public IAdvice Before(this Advisor.IReflection reflection, Action <ILGenerator> advice)
 {
     return(new Advice((_Method, _Pointer) =>
     {
         var _signature = _Method.Signature();
         var _method = new DynamicMethod(string.Empty, _Method.ReturnType, _signature, _Method.DeclaringType, true);
         var _body = _method.GetILGenerator();
         _body.Emit(advice);
         _body.Emit(_signature, false);
         _body.Emit(_Pointer, _Method.ReturnType, _signature);
         _body.Emit(OpCodes.Ret);
         _method.Prepare();
         return _method;
     }));
 }
 /// <summary>
 /// Create an advice that runs after the advised method only if it exits by throwing an exception.
 /// </summary>
 /// <param name="linq">Linq</param>
 /// <param name="advice">Expression (void) of code to invoke after the advised method</param>
 /// <returns>Advice</returns>
 static public IAdvice Throwing(this Advisor.Linq.IAfter linq, Expression advice)
 {
     return(new Advice((_Method, _Pointer) =>
     {
         var _signature = _Method.Signature();
         var _exception = Expression.Parameter(Metadata <Exception> .Type);
         if (advice == null)
         {
             return null;
         }
         if (advice.Type != Metadata.Void)
         {
             throw new NotSupportedException();
         }
         var _type = _Method.Type();
         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.BeginCatchBlock(Metadata <Exception> .Type);
             _body.Emit(OpCodes.Pop);
             _body.Emit(OpCodes.Call, Expression.Lambda(advice).CompileToMethod());
             _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_0);
             _body.BeginCatchBlock(Metadata <Exception> .Type);
             _body.Emit(OpCodes.Pop);
             _body.Emit(OpCodes.Call, Expression.Lambda(advice).CompileToMethod());
             _body.Emit(OpCodes.Rethrow);
             _body.EndExceptionBlock();
             _body.Emit(OpCodes.Ldloc_0);
         }
         _body.Emit(OpCodes.Ret);
         _method.Prepare();
         return _method;
     }));
 }
Пример #17
0
 /// <summary>
 /// Create an advice that runs before and after the advised method.
 /// </summary>
 /// <param name="basic">Basic</param>
 /// <param name="advice">Delegate to be invoked instead of the advised method : Action(object = [target instance of advised method call], object[] = [boxed arguments used to call advised method], Action = [delegate that invokes the advised method body])</param>
 /// <returns>Advice</returns>
 static public IAdvice Around(this Advisor.IBasic basic, Action <object, object[], Action> advice)
 {
     return(new Advice((_Method, _Pointer) =>
     {
         var _type = _Method.Type();
         var _signature = _Method.Signature();
         var _routine = new Closure.Routine(_Pointer, _signature, _type);
         var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.DeclaringType, true);
         var _body = _method.GetILGenerator();
         if (_type == Metadata.Void)
         {
             if (advice.Target != null)
             {
                 _body.Emit(OpCodes.Ldsfld, Advisor.Module.DefineField(advice.Target));
             }
             _body.Emit(_signature, true);
             _body.Emit(_signature, false);
             _body.Emit(OpCodes.Newobj, _routine.Constructor);
             _body.Emit(OpCodes.Ldftn, _routine.Method);
             _body.Emit(OpCodes.Newobj, Metadata <Action> .Type.GetConstructors().Single());
             _body.Emit(OpCodes.Call, advice.Method);
         }
         else
         {
             _body.DeclareLocal(_routine.Type);
             if (advice.Target != null)
             {
                 _body.Emit(OpCodes.Ldsfld, Advisor.Module.DefineField(advice.Target));
             }
             _body.Emit(_signature, true);
             _body.Emit(_signature, false);
             _body.Emit(OpCodes.Newobj, _routine.Constructor);
             _body.Emit(OpCodes.Stloc_0);
             _body.Emit(OpCodes.Ldloc_0);
             _body.Emit(OpCodes.Ldftn, _routine.Method);
             _body.Emit(OpCodes.Newobj, Metadata <Action> .Type.GetConstructors().Single());
             _body.Emit(OpCodes.Call, advice.Method);
             _body.Emit(OpCodes.Ldloc_0);
             _body.Emit(OpCodes.Ldfld, _routine.Value);
         }
         _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;
     }));
 }
Пример #19
0
 /// <summary>
 /// Create an advice that runs before the advised method.
 /// </summary>
 /// <param name="basic">Basic</param>
 /// <param name="advice">Delegate to be invoked before the advised method</param>
 /// <returns>Advice</returns>
 static public IAdvice Before(this Advisor.IBasic basic, Action advice)
 {
     return(new Advice((_Method, _Pointer) =>
     {
         var _signature = _Method.Signature();
         var _method = new DynamicMethod(string.Empty, _Method.ReturnType, _signature, _Method.DeclaringType, true);
         var _body = _method.GetILGenerator();
         if (advice.Target != null)
         {
             _body.Emit(OpCodes.Ldsfld, Advisor.Module.DefineField(advice.Target));
         }
         _body.Emit(OpCodes.Call, advice.Method);
         _body.Emit(_signature, false);
         _body.Emit(_Pointer, _Method.ReturnType, _signature);
         _body.Emit(OpCodes.Ret);
         _method.Prepare();
         return _method;
     }));
 }
Пример #20
0
 /// <summary>
 /// Create an advice that runs before and after the advised method.
 /// </summary>
 /// <typeparam name="T">Resource to create before and dispose after method execution</typeparam>
 /// <param name="basic">Basic</param>
 /// <returns>Advice</returns>
 static public IAdvice Around <T>(this Advisor.IBasic basic)
     where T : class, IDisposable, new()
 {
     return(new Advice((_Method, _Pointer) =>
     {
         var _type = _Method.Type();
         var _signature = _Method.Signature();
         var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.DeclaringType, true);
         var _body = _method.GetILGenerator();
         _body.DeclareLocal(Metadata <T> .Type);
         if (_type == Metadata.Void)
         {
             _body.BeginExceptionBlock();
             _body.Emit(OpCodes.Newobj, Metadata.Constructor(() => new T()));
             _body.Emit(OpCodes.Stloc_0);
             _body.Emit(_signature, false);
             _body.Emit(_Pointer, _type, _signature);
             _body.BeginFinallyBlock();
             _body.Emit(OpCodes.Ldloc_0);
             _body.Emit(OpCodes.Callvirt, Metadata <IDisposable> .Method(_Disposable => _Disposable.Dispose()));
             _body.EndExceptionBlock();
         }
         else
         {
             _body.DeclareLocal(_type);
             _body.BeginExceptionBlock();
             _body.Emit(OpCodes.Newobj, Metadata.Constructor(() => new T()));
             _body.Emit(OpCodes.Stloc_0);
             _body.Emit(_signature, false);
             _body.Emit(_Pointer, _type, _signature);
             _body.Emit(OpCodes.Stloc_1);
             _body.BeginFinallyBlock();
             _body.Emit(OpCodes.Ldloc_0);
             _body.Emit(OpCodes.Callvirt, Metadata <IDisposable> .Method(_Disposable => _Disposable.Dispose()));
             _body.EndExceptionBlock();
             _body.Emit(OpCodes.Ldloc_1);
         }
         _body.Emit(OpCodes.Ret);
         _method.Prepare();
         return _method;
     }));
 }
Пример #21
0
 /// <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;
     }));
 }
Пример #22
0
 /// <summary>
 /// Create an advice that runs before and after the advised method.
 /// </summary>
 /// <param name="basic">Basic</param>
 /// <param name="advice">Delegate to be invoked instead of the advised method : Func(object = [target instance of advised method call], object[] = [boxed arguments used to call advised method], Func() = [delegate that invokes advised method body (return boxed return value or null if return type is void)]) return boxed return value (null if return type is void)</param>
 /// <returns>Advice</returns>
 static public IAdvice Around(this Advisor.IBasic basic, Func <object, object[], Func <object>, object> advice)
 {
     return(new Advice((_Method, _Pointer) =>
     {
         var _type = _Method.Type();
         var _signature = _Method.Signature();
         var _function = new Closure.Function(_Pointer, _signature, _type);
         var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.DeclaringType, true);
         var _body = _method.GetILGenerator();
         if (advice.Target != null)
         {
             _body.Emit(OpCodes.Ldsfld, Advisor.Module.DefineField(advice.Target));
         }
         _body.Emit(_signature, true);
         _body.Emit(_signature, false);
         _body.Emit(OpCodes.Newobj, _function.Constructor);
         _body.Emit(OpCodes.Ldftn, _function.Method);
         _body.Emit(OpCodes.Newobj, Metadata <Func <object> > .Type.GetConstructors().Single());
         _body.Emit(OpCodes.Call, advice.Method);
         if (_type == Metadata.Void)
         {
             _body.Emit(OpCodes.Pop);
         }
         else
         {
             if (_type.IsValueType)
             {
                 _body.Emit(OpCodes.Unbox_Any, _type);
             }
             else
             {
                 _body.Emit(OpCodes.Castclass, _type);
             }
         }
         _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="linq">Linq</param>
 /// <param name="advice">Expression (void) of code to be invoked after the advised method</param>
 /// <returns>Advice</returns>
 static public IAdvice Returning(this Advisor.Linq.IAfter linq, Expression advice)
 {
     return(new Advice((_Method, _Pointer) =>
     {
         var _signature = _Method.Signature();
         if (advice == null)
         {
             return _Method;
         }
         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();
         _body.Emit(_signature, false);
         _body.Emit(_Pointer, _Method.ReturnType, _signature);
         _body.Emit(OpCodes.Call, Expression.Lambda(advice).CompileToMethod());
         _body.Emit(OpCodes.Ret);
         _method.Prepare();
         return _method;
     }));
 }
Пример #24
0
 /// <summary>
 /// Create an advice that runs after the advised method only if it exits by throwing an exception.
 /// </summary>
 /// <param name="reflection">Reflection</param>
 /// <param name="advice">Delegate used to emit code to be invoked after the advised method</param>
 /// <returns>Advice</returns>
 static public Advice Throwing(this Advice.Style.Reflection.IAfter reflection, Action <ILGenerator> advice)
 {
     return(new Advice((_Method, _Pointer, _Boundary) =>
     {
         var _type = _Method.ReturnType();
         var _signature = _Method.Signature();
         var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.Module, true);
         var _body = _method.GetILGenerator();
         if (_Boundary != null) //TODO dynamic implementation of boundary will avoid redirection overhead.
         {
             var _action = new DynamicMethod(string.Empty, Runtime.Void, new Type[] { Metadata <object> .Type, Metadata <object> .Type, Metadata <object[]> .Type, Metadata <Exception> .Type }, true);
             var _redirection = _action.GetILGenerator();
             if (_signature.Instance != null)
             {
                 _redirection.Emit(OpCodes.Ldarg_1);
                 if (_signature.Instance.IsValueType)
                 {
                     _redirection.Emit(OpCodes.Unbox_Any, _signature.Instance);
                 }
                 else
                 {
                     _redirection.Emit(OpCodes.Castclass, _signature.Instance);
                 }
             }
             for (var _index = 0; _index < _signature.Length; _index++)
             {
                 var _parameter = _signature[_index];
                 _redirection.Emit(OpCodes.Ldarg_2);
                 _redirection.Emit(OpCodes.Ldc_I4, _index); //TODO shortcut
                 _redirection.Emit(OpCodes.Ldelem_Ref);
                 if (_parameter.IsValueType)
                 {
                     _redirection.Emit(OpCodes.Unbox_Any, _parameter);
                 }
                 else
                 {
                     _redirection.Emit(OpCodes.Castclass, _parameter);
                 }
             }
             if (_type != Runtime.Void)
             {
                 var _exception = Advice.Module.DefineThreadField("<Exception>", Metadata <Exception> .Type);
                 _redirection.Emit(OpCodes.Ldarg_3);
                 _redirection.Emit(OpCodes.Stsfld, _exception);
                 _body.Emit(OpCodes.Ldsfld, _exception);
                 _body.Emit(OpCodes.Ldnull);
                 _body.Emit(OpCodes.Stsfld, _exception);
             }
             _body.Emit(advice);
             _body.Emit(OpCodes.Ret);
             _method.Prepare();
             _redirection.Emit(OpCodes.Call, _method);
             _redirection.Emit(OpCodes.Ret);
             _action.Prepare();
             return _Boundary.Combine(new Advice.Boundary.Advanced.After.Throwing.Singleton(_Method, _action.CreateDelegate(Metadata <Action <object, object[], Exception> > .Type, null) as Action <object, object[], Exception>));
         }
         else
         {
             if (_type == Runtime.Void)
             {
                 _body.BeginExceptionBlock();
                 _body.Emit(_signature, false);
                 _body.Emit(_Pointer, _type, _signature);
                 _body.BeginCatchBlock(Metadata <Exception> .Type);
                 _body.Emit(advice);
                 _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_0);
                 _body.BeginCatchBlock(Metadata <Exception> .Type);
                 _body.Emit(advice);
                 _body.Emit(OpCodes.Rethrow);
                 _body.EndExceptionBlock();
                 _body.Emit(OpCodes.Ldloc_0);
             }
             _body.Emit(OpCodes.Ret);
             _method.Prepare();
             return _method;
         }
     }));
 }
Пример #25
0
                private MethodInfo Decorate(IntPtr pointer, Func <IAdvice> advise)
                {
                    var _type       = this.Method.ReturnType();
                    var _parameters = this.Method.GetParameters();
                    var _signature  = this.Method.Signature();
                    var _method     = new DynamicMethod(string.Empty, _type, _signature, this.Method.DeclaringType, true);
                    var _body       = _method.GetILGenerator();
                    var _factory    = _body.DeclareLocal(Metadata <Func <IAdvice> > .Type);
                    var _backup     = _body.DeclareLocal(Metadata <Exception> .Type);
                    var _exception  = _body.DeclareLocal(Metadata <Exception> .Type);

                    _body.Emit(OpCodes.Ldsfld, Aspect.Directory.Entry.Module.DefineField(Guid.NewGuid().ToString("N"), advise));
                    _body.Emit(OpCodes.Callvirt, Metadata <Func <IAdvice> > .Method(_Function => _Function.Invoke()));
                    _body.Emit(OpCodes.Stloc_0);
                    if (this.Method.IsStatic)
                    {
                        for (var _index = 0; _index < _signature.Length; _index++)
                        {
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Ldarga_S, _index);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Argument(ref Metadata <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_parameters[_index].ParameterType));
                        }
                        _body.Emit(OpCodes.Ldloc_0);
                        _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Begin()));
                        _body.BeginExceptionBlock();
                        _body.Emit(_signature, false);
                        _body.Emit(pointer, _type, _signature);
                        if (_type == Runtime.Void)
                        {
                            var _return  = _body.DefineLabel();
                            var _leave   = _body.DefineLabel();
                            var _rethrow = _body.DefineLabel();
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Return()));
                            _body.Emit(OpCodes.Leave, _return);
                            _body.BeginCatchBlock(Metadata <Exception> .Type);
                            _body.Emit(OpCodes.Stloc_1);
                            _body.Emit(OpCodes.Ldloc_1);
                            _body.Emit(OpCodes.Stloc_2);
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Ldloca_S, 2);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Throw(ref Metadata <Exception> .Value)));
                            _body.Emit(OpCodes.Ldloc_2);
                            _body.Emit(OpCodes.Brfalse, _leave);
                            _body.Emit(OpCodes.Ldloc_1);
                            _body.Emit(OpCodes.Ldloc_2);
                            _body.Emit(OpCodes.Beq, _rethrow);
                            _body.Emit(OpCodes.Ldloc_2);
                            _body.Emit(OpCodes.Throw);
                            _body.Emit(OpCodes.Br, _leave);
                            _body.MarkLabel(_rethrow);
                            _body.Emit(OpCodes.Rethrow);
                            _body.MarkLabel(_leave);
                            _body.Emit(OpCodes.Leave, _return);
                            _body.BeginFinallyBlock();
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Dispose()));
                            _body.EndExceptionBlock();
                            _body.MarkLabel(_return);
                            _body.Emit(OpCodes.Ret);
                        }
                        else
                        {
                            var _return  = _body.DefineLabel();
                            var _leave   = _body.DefineLabel();
                            var _rethrow = _body.DefineLabel();
                            _body.DeclareLocal(_type);
                            _body.Emit(OpCodes.Stloc_3);
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Ldloca_S, 3);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Return(ref Metadata <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_type));
                            _body.Emit(OpCodes.Leave, _return);
                            _body.BeginCatchBlock(Metadata <Exception> .Type);
                            _body.Emit(OpCodes.Stloc_1);
                            _body.Emit(OpCodes.Ldloc_1);
                            _body.Emit(OpCodes.Stloc_2);
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Ldloca_S, 2);
                            _body.Emit(OpCodes.Ldloca_S, 3);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Throw(ref Metadata <Exception> .Value, ref Metadata <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_type));
                            _body.Emit(OpCodes.Ldloc_2);
                            _body.Emit(OpCodes.Brfalse, _leave);
                            _body.Emit(OpCodes.Ldloc_1);
                            _body.Emit(OpCodes.Ldloc_2);
                            _body.Emit(OpCodes.Beq, _rethrow);
                            _body.Emit(OpCodes.Ldloc_2);
                            _body.Emit(OpCodes.Throw);
                            _body.Emit(OpCodes.Br, _leave);
                            _body.MarkLabel(_rethrow);
                            _body.Emit(OpCodes.Rethrow);
                            _body.MarkLabel(_leave);
                            _body.Emit(OpCodes.Leave, _return);
                            _body.BeginFinallyBlock();
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Dispose()));
                            _body.EndExceptionBlock();
                            _body.MarkLabel(_return);
                            _body.Emit(OpCodes.Ldloc_3);
                            _body.Emit(OpCodes.Ret);
                        }
                    }
                    else
                    {
                        _body.Emit(OpCodes.Ldloc_0);
                        _body.Emit(OpCodes.Ldarg_0);
                        _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Instance(Metadata <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(this.Method.DeclaringType));
                        for (var _index = 0; _index < _parameters.Length; _index++)
                        {
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Ldarga_S, _index + 1);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Argument(ref Metadata <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_parameters[_index].ParameterType));
                        }
                        _body.Emit(OpCodes.Ldloc_0);
                        _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Begin()));
                        _body.BeginExceptionBlock();
                        _body.Emit(_signature, false);
                        _body.Emit(pointer, _type, _signature);
                        if (_type == Runtime.Void)
                        {
                            var _return  = _body.DefineLabel();
                            var _leave   = _body.DefineLabel();
                            var _rethrow = _body.DefineLabel();
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Return()));
                            _body.Emit(OpCodes.Leave, _return);
                            _body.BeginCatchBlock(Metadata <Exception> .Type);
                            _body.Emit(OpCodes.Stloc_1);
                            _body.Emit(OpCodes.Ldloc_1);
                            _body.Emit(OpCodes.Stloc_2);
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Ldloca_S, 2);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Throw(ref Metadata <Exception> .Value)));
                            _body.Emit(OpCodes.Ldloc_2);
                            _body.Emit(OpCodes.Brfalse, _leave);
                            _body.Emit(OpCodes.Ldloc_1);
                            _body.Emit(OpCodes.Ldloc_2);
                            _body.Emit(OpCodes.Beq, _rethrow);
                            _body.Emit(OpCodes.Ldloc_2);
                            _body.Emit(OpCodes.Throw);
                            _body.Emit(OpCodes.Br, _leave);
                            _body.MarkLabel(_rethrow);
                            _body.Emit(OpCodes.Rethrow);
                            _body.MarkLabel(_leave);
                            _body.Emit(OpCodes.Leave, _return);
                            _body.BeginFinallyBlock();
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Dispose()));
                            _body.EndExceptionBlock();
                            _body.MarkLabel(_return);
                            _body.Emit(OpCodes.Ret);
                        }
                        else
                        {
                            var _return  = _body.DefineLabel();
                            var _leave   = _body.DefineLabel();
                            var _rethrow = _body.DefineLabel();
                            _body.DeclareLocal(_type);
                            _body.Emit(OpCodes.Stloc_3);
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Ldloca_S, 3);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Return(ref Metadata <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_type));
                            _body.Emit(OpCodes.Leave, _return);
                            _body.BeginCatchBlock(Metadata <Exception> .Type);
                            _body.Emit(OpCodes.Stloc_1);
                            _body.Emit(OpCodes.Ldloc_1);
                            _body.Emit(OpCodes.Stloc_2);
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Ldloca_S, 2);
                            _body.Emit(OpCodes.Ldloca_S, 3);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Throw(ref Metadata <Exception> .Value, ref Metadata <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_type));
                            _body.Emit(OpCodes.Ldloc_2);
                            _body.Emit(OpCodes.Brfalse, _leave);
                            _body.Emit(OpCodes.Ldloc_1);
                            _body.Emit(OpCodes.Ldloc_2);
                            _body.Emit(OpCodes.Beq, _rethrow);
                            _body.Emit(OpCodes.Ldloc_2);
                            _body.Emit(OpCodes.Throw);
                            _body.Emit(OpCodes.Br, _leave);
                            _body.MarkLabel(_rethrow);
                            _body.Emit(OpCodes.Rethrow);
                            _body.MarkLabel(_leave);
                            _body.Emit(OpCodes.Leave, _return);
                            _body.BeginFinallyBlock();
                            _body.Emit(OpCodes.Ldloc_0);
                            _body.Emit(OpCodes.Callvirt, Metadata <IAdvice> .Method(_IAdvice => _IAdvice.Dispose()));
                            _body.EndExceptionBlock();
                            _body.MarkLabel(_return);
                            _body.Emit(OpCodes.Ldloc_3);
                            _body.Emit(OpCodes.Ret);
                        }
                    }
                    _method.Prepare();
                    return(_method);
                }
Пример #26
0
                unsafe internal Entry(Type type, MethodInfo method, IntPtr pointer, Activity activity)
                {
                    method.Prepare();
                    this.Type            = type;
                    this.Method          = method;
                    this.m_Pointer       = pointer;
                    this.Activity        = activity;
                    this.m_Aspectization = new LinkedList <IAspect>();
                    this.m_Dictionary    = new Dictionary <IAspect, Activity>();
                    if (method.IsVirtual)
                    {
                        return;
                    }

                    var _type = Entry.m_Module.DefineType(string.Concat(Metadata <Delegate> .Type.Name, Guid.NewGuid().ToString("N")), TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Abstract);

                    switch (IntPtr.Size)
                    {
                    case 4: _type.DefineField(Metadata <Entry> .Field(_Activity => _Activity.m_Pointer).Name, Metadata <int> .Type, FieldAttributes.Static | FieldAttributes.Public); break;

                    case 8: _type.DefineField(Metadata <Entry> .Field(_Activity => _Activity.m_Pointer).Name, Metadata <long> .Type, FieldAttributes.Static | FieldAttributes.Public); break;

                    default: throw new NotSupportedException();
                    }
                    var _field     = _type.CreateType().GetFields(BindingFlags.Static | BindingFlags.Public).Single();
                    var _signature = this.Method.Signature();
                    var _method    = new DynamicMethod(method.Name, this.Method.ReturnType, _signature, this.Method.DeclaringType, true);
                    var _body      = _method.GetILGenerator();

                    for (var _index = 0; _index < _signature.Length; _index++)
                    {
                        switch (_index)
                        {
                        case 0: _body.Emit(OpCodes.Ldarg_0); break;

                        case 1: _body.Emit(OpCodes.Ldarg_1); break;

                        case 2: _body.Emit(OpCodes.Ldarg_2); break;

                        case 3: _body.Emit(OpCodes.Ldarg_3); break;

                        default: _body.Emit(OpCodes.Ldarg_S, _index); break;
                        }
                    }
                    _body.Emit(OpCodes.Ldsflda, _field);
                    _body.Emit(OpCodes.Volatile);
                    _body.Emit(OpCodes.Ldobj, _field.FieldType);
                    _body.EmitCalli(OpCodes.Calli, CallingConventions.Standard, method.ReturnType, _signature, null);
                    _body.Emit(OpCodes.Ret);
                    _method.Prepare();
                    switch (IntPtr.Size)
                    {
                    case 4:
                        *((int *)(this.m_Pointer)) = _method.Pointer().ToInt32();
                        this.m_Setup = Expression.Lambda <Action <IntPtr> >(Expression.Assign(Expression.Field(null, _field), Expression.Call(Parameter <IntPtr> .Expression, Metadata <IntPtr> .Method(_Pointer => _Pointer.ToInt32()))), Parameter <IntPtr> .Expression).Compile();
                        break;

                    case 8:
                        *((long *)(this.m_Pointer)) = _method.Pointer().ToInt64();
                        this.m_Setup = Expression.Lambda <Action <IntPtr> >(Expression.Assign(Expression.Field(null, _field), Expression.Call(Parameter <IntPtr> .Expression, Metadata <IntPtr> .Method(_Pointer => _Pointer.ToInt64()))), Parameter <IntPtr> .Expression).Compile();
                        break;

                    default: throw new NotSupportedException();
                    }
                    this.m_Setup(activity.Pointer);
                }
Пример #27
0
 /// <summary>
 /// Create an advice that runs after the advised method regardless of its outcome.
 /// </summary>
 /// <param name="basic">Basic</param>
 /// <param name="advice">Delegate to be invoked after the advised method</param>
 /// <returns>Advice</returns>
 static public Advice After(this Advice.Style.IBasic basic, Action advice)
 {
     return(new Advice((_Method, _Pointer, _Boundary) =>
     {
         if (_Boundary != null)
         {
             return _Boundary.Combine(new Advice.Boundary.Basic.After.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.DeclareLocal(Metadata <bool> .Type);
         var _realized = _body.DefineLabel();
         if (_type == Runtime.Void)
         {
             _body.BeginExceptionBlock();
             _body.Emit(_signature, false);
             _body.Emit(_Pointer, _type, _signature);
             _body.Emit(OpCodes.Ldc_I4_1);
             _body.Emit(OpCodes.Stloc_0);
             if (advice.Target != null)
             {
                 _body.Emit(OpCodes.Ldsfld, Advice.Module.DefineField(advice.Target));
             }
             _body.Emit(OpCodes.Call, advice.Method);
             _body.BeginCatchBlock(Metadata <Exception> .Type);
             _body.Emit(OpCodes.Pop);
             _body.Emit(OpCodes.Ldloc_0);
             _body.Emit(OpCodes.Brtrue, _realized);
             if (advice.Target != null)
             {
                 _body.Emit(OpCodes.Ldsfld, Advice.Module.DefineField(advice.Target));
             }
             _body.Emit(OpCodes.Call, advice.Method);
             _body.MarkLabel(_realized);
             _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.Emit(OpCodes.Ldc_I4_1);
             _body.Emit(OpCodes.Stloc_0);
             if (advice.Target != null)
             {
                 _body.Emit(OpCodes.Ldsfld, Advice.Module.DefineField(advice.Target));
             }
             _body.Emit(OpCodes.Call, advice.Method);
             _body.BeginCatchBlock(Metadata <Exception> .Type);
             _body.Emit(OpCodes.Pop);
             _body.Emit(OpCodes.Ldloc_0);
             _body.Emit(OpCodes.Brtrue, _realized);
             if (advice.Target != null)
             {
                 _body.Emit(OpCodes.Ldsfld, Advice.Module.DefineField(advice.Target));
             }
             _body.Emit(OpCodes.Call, advice.Method);
             _body.MarkLabel(_realized);
             _body.Emit(OpCodes.Rethrow);
             _body.EndExceptionBlock();
             _body.Emit(OpCodes.Ldloc_1);
         }
         _body.Emit(OpCodes.Ret);
         _method.Prepare();
         return _method;
     }));
 }
Пример #28
0
 static public Advice Boundary(this Advice.Style.IBasic basic, Advice.Boundary.IFactory factory)
 {
     //TODO missing dispose call!
     return(new Advice((_Method, _Pointer, _Boundary) =>
     {
         if (_Boundary != null)
         {
             return _Boundary.Combine(factory);
         }
         var _type = _Method.ReturnType();
         var _parameters = _Method.GetParameters();
         var _signature = _Method.Signature();
         var _routine = new Closure.Routine(_Pointer, _signature, _type);
         var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.DeclaringType, true);
         var _body = _method.GetILGenerator();
         var _boundary = _body.DeclareLocal(Metadata <Advice.IBoundary> .Type);
         var _backup = _body.DeclareLocal(Metadata <Exception> .Type);
         var _exception = _body.DeclareLocal(Metadata <Exception> .Type);
         _body.Emit(OpCodes.Ldsfld, Advice.Module.DefineField(Guid.NewGuid().ToString("N"), factory));
         _body.Emit(OpCodes.Callvirt, Metadata <Advice.Boundary.IFactory> .Method(_Factory => _Factory.Create()));
         _body.Emit(OpCodes.Stloc_0);
         if (_Method.IsStatic)
         {
             for (var _index = 0; _index < _signature.Length; _index++)
             {
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Ldsfld, Runtime.Inventory.Parameter(_parameters[_index]));
                 _body.Emit(OpCodes.Ldarga_S, _index);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Argument(Argument <ParameterInfo> .Value, ref Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_parameters[_index].ParameterType));
             }
             _body.Emit(OpCodes.Ldloc_0);
             _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Begin()));
             _body.BeginExceptionBlock();
             _body.Emit(_signature, false);
             _body.Emit(_Pointer, _type, _signature);
             if (_type == Runtime.Void)
             {
                 var _return = _body.DefineLabel();
                 var _null = _body.DefineLabel();
                 var _rethrow = _body.DefineLabel();
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Return()));
                 _body.Emit(OpCodes.Leave, _return);
                 _body.BeginCatchBlock(Metadata <Exception> .Type);
                 _body.Emit(OpCodes.Stloc_1);
                 _body.Emit(OpCodes.Ldloc_1);
                 _body.Emit(OpCodes.Stloc_2);
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Ldloca_S, 2);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Throw(ref Argument <Exception> .Value)));
                 _body.Emit(OpCodes.Ldloc_2);
                 _body.Emit(OpCodes.Brfalse, _null);
                 _body.Emit(OpCodes.Ldloc_1);
                 _body.Emit(OpCodes.Ldloc_2);
                 _body.Emit(OpCodes.Beq, _rethrow);
                 _body.Emit(OpCodes.Ldloc_2);
                 _body.Emit(OpCodes.Throw);
                 _body.MarkLabel(_rethrow);
                 _body.Emit(OpCodes.Rethrow);
                 _body.MarkLabel(_null);
                 _body.Emit(OpCodes.Leave, _return);
                 _body.EndExceptionBlock();
                 _body.MarkLabel(_return);
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Dispose()));
                 _body.Emit(OpCodes.Ret);
             }
             else
             {
                 var _return = _body.DefineLabel();
                 var _null = _body.DefineLabel();
                 var _rethrow = _body.DefineLabel();
                 _body.DeclareLocal(_type);
                 _body.Emit(OpCodes.Stloc_3);
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Ldloca_S, 3);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Return(ref Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_type));
                 _body.Emit(OpCodes.Leave, _return);
                 _body.BeginCatchBlock(Metadata <Exception> .Type);
                 _body.Emit(OpCodes.Stloc_1);
                 _body.Emit(OpCodes.Ldloc_1);
                 _body.Emit(OpCodes.Stloc_2);
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Ldloca_S, 2);
                 _body.Emit(OpCodes.Ldloca_S, 3);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Throw(ref Argument <Exception> .Value, ref Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod());
                 _body.Emit(OpCodes.Ldloc_2);
                 _body.Emit(OpCodes.Brfalse, _null);
                 _body.Emit(OpCodes.Ldloc_1);
                 _body.Emit(OpCodes.Ldloc_2);
                 _body.Emit(OpCodes.Beq, _rethrow);
                 _body.Emit(OpCodes.Ldloc_2);
                 _body.Emit(OpCodes.Throw);
                 _body.MarkLabel(_rethrow);
                 _body.Emit(OpCodes.Rethrow);
                 _body.MarkLabel(_null);
                 _body.Emit(OpCodes.Leave, _return);
                 _body.EndExceptionBlock();
                 _body.MarkLabel(_return);
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Dispose()));
                 _body.Emit(OpCodes.Ldloc_3);
                 _body.Emit(OpCodes.Ret);
             }
         }
         else
         {
             _body.Emit(OpCodes.Ldloc_0);
             _body.Emit(OpCodes.Ldarg_0);
             _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Instance(Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_Method.DeclaringType));
             for (var _index = 0; _index < _parameters.Length; _index++)
             {
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Ldsfld, Runtime.Inventory.Parameter(_parameters[_index]));
                 _body.Emit(OpCodes.Ldarga_S, _index + 1);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Argument(Argument <ParameterInfo> .Value, ref Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_parameters[_index].ParameterType));
             }
             _body.Emit(OpCodes.Ldloc_0);
             _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Begin()));
             _body.BeginExceptionBlock();
             _body.Emit(_signature, false);
             _body.Emit(_Pointer, _type, _signature);
             if (_type == Runtime.Void)
             {
                 var _return = _body.DefineLabel();
                 var _null = _body.DefineLabel();
                 var _rethrow = _body.DefineLabel();
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Return()));
                 _body.Emit(OpCodes.Leave, _return);
                 _body.BeginCatchBlock(Metadata <Exception> .Type);
                 _body.Emit(OpCodes.Stloc_1);
                 _body.Emit(OpCodes.Ldloc_1);
                 _body.Emit(OpCodes.Stloc_2);
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Ldloca_S, 2);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Throw(ref Argument <Exception> .Value)));
                 _body.Emit(OpCodes.Ldloc_2);
                 _body.Emit(OpCodes.Brfalse, _null);
                 _body.Emit(OpCodes.Ldloc_1);
                 _body.Emit(OpCodes.Ldloc_2);
                 _body.Emit(OpCodes.Beq, _rethrow);
                 _body.Emit(OpCodes.Ldloc_2);
                 _body.Emit(OpCodes.Throw);
                 _body.MarkLabel(_rethrow);
                 _body.Emit(OpCodes.Rethrow);
                 _body.MarkLabel(_null);
                 _body.Emit(OpCodes.Leave, _return);
                 _body.EndExceptionBlock();
                 _body.MarkLabel(_return);
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Dispose()));
                 _body.Emit(OpCodes.Ret);
             }
             else
             {
                 var _return = _body.DefineLabel();
                 var _null = _body.DefineLabel();
                 var _rethrow = _body.DefineLabel();
                 _body.DeclareLocal(_type);
                 _body.Emit(OpCodes.Stloc_3);
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Ldloca_S, 3);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Return(ref Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_type));
                 _body.Emit(OpCodes.Leave, _return);
                 _body.BeginCatchBlock(Metadata <Exception> .Type);
                 _body.Emit(OpCodes.Stloc_1);
                 _body.Emit(OpCodes.Ldloc_1);
                 _body.Emit(OpCodes.Stloc_2);
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Ldloca_S, 2);
                 _body.Emit(OpCodes.Ldloca_S, 3);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Throw(ref Argument <Exception> .Value, ref Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_type));
                 _body.Emit(OpCodes.Ldloc_2);
                 _body.Emit(OpCodes.Brfalse, _null);
                 _body.Emit(OpCodes.Ldloc_1);
                 _body.Emit(OpCodes.Ldloc_2);
                 _body.Emit(OpCodes.Beq, _rethrow);
                 _body.Emit(OpCodes.Ldloc_2);
                 _body.Emit(OpCodes.Throw);
                 _body.MarkLabel(_rethrow);
                 _body.Emit(OpCodes.Rethrow);
                 _body.MarkLabel(_null);
                 _body.Emit(OpCodes.Leave, _return);
                 _body.EndExceptionBlock();
                 _body.MarkLabel(_return);
                 _body.Emit(OpCodes.Ldloc_0);
                 _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Dispose()));
                 _body.Emit(OpCodes.Ldloc_3);
                 _body.Emit(OpCodes.Ret);
             }
         }
         _method.Prepare();
         return _method;
     }));
 }