/// <summary> /// Collect a new interceptor. /// </summary> /// <param name="interceptor">The interceptor to collect.</param> /// <param name="order">The order in the interceptor chain to build.</param> /// <returns>The current inteceptor builder.</returns> /// <exception cref="ArgumentNullException">The specified <paramref name="interceptor"/> is null.</exception> public IInterceptorBuilder Use(InterceptorDelegate interceptor, int order) { Guard.ArgumentNotNull(interceptor, "interceptor"); InterceptorDelegate wrapper = next => (async context => { try { await interceptor(next)(context); } catch (Exception ex) { if (!context.ExceptionHandled) { throw new InterceptionException(Resources.ExceptionInterceptionError, ex); } else { throw ex; } } }); _interceptors.Add(new Tuple <int, InterceptorDelegate>(order, wrapper)); return(this); }
protected override Task InterceptAsync(IInvocation invocation, Func <IInvocation, Task> proceed) { var invocationContext = new DynamicProxyInvocationContext(invocation); InterceptDelegate next = context => proceed(invocation); return(_interceptor(next)(invocationContext)); }
/// <summary> /// Invoke interceptor and target method. /// </summary> /// <param name="interceptor">A <see cref="InterceptorDelegate"/> representing interceptor applied to target method.</param> /// <param name="handler">A <see cref="InterceptDelegate"/> used to invoke the target method.</param> /// <param name="context">A <see cref="InvocationContext"/> representing the current method invocation context.</param> /// <returns>The task to invoke interceptor and target method.</returns> public static Task InvokeHandler(InterceptorDelegate interceptor, InterceptDelegate handler, InvocationContext context) { async Task Wrap(InvocationContext invocationContext) { await handler(invocationContext); if (invocationContext.ReturnValue is Task task) { await task; } } return(interceptor(Wrap)(context)); }
/// <summary> /// Invoke interceptor and target method. /// </summary> /// <param name="interceptor">A <see cref="InterceptorDelegate"/> representing interceptor applied to target method.</param> /// <param name="handler">A <see cref="InterceptDelegate"/> used to invoke the target method.</param> /// <param name="context">A <see cref="InvocationContext"/> representing the current method invocation context.</param> /// <returns>The task to invoke interceptor and target method.</returns> public static Task InvokeHandler(InterceptorDelegate interceptor, InterceptDelegate handler, InvocationContext context) { InterceptDelegate wrapper = async _ => { await handler(_); var task = _.ReturnValue as Task; if (null != task) { await task; } }; return(interceptor(wrapper)(context)); }
/// <summary> /// Register the interceptor of <paramref name="interceptorType"/> to specified interceptor chain builder. /// </summary> /// <param name="builder">The interceptor chain builder to which the interceptor is registered.</param> /// <param name="interceptorType">The interceptor type.</param> /// <param name="order">The order for the registered interceptor in the built chain.</param> /// <param name="arguments">The non-injected arguments passes to the constructor.</param> /// <returns>The interceptor chain builder with registered interceptor.</returns> /// <exception cref="ArgumentNullException">The argument <paramref name="builder"/> is null.</exception> /// <exception cref="ArgumentNullException">The argument <paramref name="interceptorType"/> is null.</exception> public static IInterceptorChainBuilder Use(this IInterceptorChainBuilder builder, Type interceptorType, int order, params object[] arguments) { Guard.ArgumentNotNull(builder, nameof(builder)); Guard.ArgumentNotNull(interceptorType, nameof(interceptorType)); object instance = ActivatorUtilities.CreateInstance(builder.ServiceProvider, interceptorType, arguments); InterceptorDelegate interceptor = next => { return(async context => { context.Next = next; InvokeDelegate invoker; if (TryGetInvoke(interceptorType, out invoker)) { await invoker(instance, context, builder.ServiceProvider); } else { throw new ArgumentException("Invalid interceptor type", "interceptorType"); } }); }; return(builder.Use(interceptor, order)); }
public void GetInterceptors() { var invokeMethod = typeof(Foobar).GetMethod("Invoke"); var fooProperty = typeof(Foobar).GetProperty("Foo"); InterceptorDelegate interceptor = next => null; var interceptors = new Dictionary <MethodInfo, InterceptorDelegate> { [invokeMethod] = interceptor, [fooProperty.GetMethod] = interceptor }; var interception = new InterceptorDecoration(interceptors, typeof(Foobar).GetInterfaceMap(typeof(IFoobar))); Assert.False(interception.IsEmpty); Assert.True(interception.Contains(invokeMethod)); Assert.True(interception.Contains(fooProperty.GetMethod)); Assert.False(interception.Contains(fooProperty.SetMethod)); Assert.True(interception.IsInterceptable(invokeMethod)); Assert.True(interception.IsInterceptable(fooProperty.GetMethod)); Assert.False(interception.IsInterceptable(fooProperty.SetMethod)); Assert.Same(interceptor, interception.GetInterceptor(invokeMethod)); Assert.Same(interceptor, interception.GetInterceptor(fooProperty.GetMethod)); Assert.Same(typeof(Foobar).GetMethod("Invoke"), interception.GetTargetMethod(typeof(IFoobar).GetMethod("Invoke"))); }
/// <summary> /// Method to unregister an interceptor /// </summary> /// <param name="direction">Defines if interceptor is for: publish or subscribe</param> /// <param name="registrationGuid">Goid which was returned from the register call</param> public static void UnRegister(InterceptDirection direction, Guid registrationGuid) { if (direction != InterceptDirection.Publish && direction != InterceptDirection.Subscribe) { return; } if (direction == InterceptDirection.Subscribe) { if (subscribeRegistrationGuid == registrationGuid) { subscribeInterceptor = null; subscribeRegistrationGuid = Guid.Empty; } } else { if (publishRegistrationGuid == registrationGuid) { publishInterceptor = null; publishRegistrationGuid = Guid.Empty; } } return; }
public async Task <TResult> InvokeAsync <TResult>(InterceptorDelegate interceptor, InvocationContext context) { if (_collections.TryGetValue(context.Method, out InterceptorMiddleware middleware)) { await middleware(interceptor)(context); } else { await interceptor(context); } if (context.Return is Task <TResult> taskWithResult) { return(await taskWithResult); } else if (context.Return is Task task) { await task; return(default(TResult)); } else { throw new InvalidCastException($"无法将返回值类型转换为{typeof(Task<TResult>)}"); } }
public void Wrap() { var fooMethod = typeof(IFoobar).GetMethod("Foo"); var barProperty = typeof(IFoobar).GetProperty("Bar"); InterceptorDelegate interceptor = next => (context => Task.Run(() => _flag++)); var interceptors = new Dictionary <MethodInfo, InterceptorDelegate> { [fooMethod] = interceptor, [barProperty.GetMethod] = interceptor }; var interception = new InterceptorDecoration(interceptors, typeof(Foobar).GetInterfaceMap(typeof(IFoobar))); var proxy = new InterfaceDynamicProxyGenerator(new DynamicProxyFactoryCache()) .Wrap(typeof(IFoobar), new Foobar(), interception) as IFoobar; _flag = 0; proxy.Foo(); Assert.Equal(1, _flag); var bar = proxy.Bar; Assert.Equal(2, _flag); proxy.Bar = "111"; Assert.Equal(2, _flag); }
/// <summary> /// Initializes a new instance of the <see cref="PropertyBasedInterceptorDecoration"/> class. /// </summary> /// <param name="property">The property.</param> /// <param name="getMethodBasedInterceptor">The get method based interceptor.</param> /// <param name="setMethodBasedInterceptor">The set method based interceptor.</param> /// <exception cref="ArgumentNullException"> Specified <paramref name="property"/> is null.</exception> /// <exception cref="ArgumentNullException"> Specified <paramref name="getMethodBasedInterceptor"/> and <paramref name="setMethodBasedInterceptor"/> are both null.</exception> public PropertyBasedInterceptorDecoration( PropertyInfo property, InterceptorDelegate getMethodBasedInterceptor, InterceptorDelegate setMethodBasedInterceptor) { this.Property = Guard.ArgumentNotNull(property, nameof(property)); if (getMethodBasedInterceptor == null && setMethodBasedInterceptor == null) { throw new ArgumentException(Resources.ExceptionGetAndSetMethodBasedInterceptorCannotBeNull); } if (getMethodBasedInterceptor != null) { var getMethod = property.GetMethod; if (null != getMethod) { this.GetMethodBasedInterceptor = new MethodBasedInterceptorDecoration(getMethod, getMethodBasedInterceptor); } } if (setMethodBasedInterceptor != null) { var setMethod = property.SetMethod; if (null != setMethod) { this.SetMethodBasedInterceptor = new MethodBasedInterceptorDecoration(setMethod, setMethodBasedInterceptor); } } }
public override async Task Intercept(InvocationContext context, InterceptorDelegate next) { this.Log.Write("方法执行之前,当前参数值:" + string.Join(",", context.Arguments)); await next(context); Thread.Sleep(1000); this.Log.Write("方法执行之后,当前返回值:" + context.Return); }
private T CreateProxy <T>(T target, InterceptorDelegate interceptor, MethodInfo method) { var methodBasedInterceptor = new MethodBasedInterceptorDecoration(method, interceptor); var decoration = new InterceptorDecoration(new MethodBasedInterceptorDecoration[] { methodBasedInterceptor }, null); var generator = DynamicProxyClassGenerator.CreateInterfaceGenerator(typeof(T), decoration); var proxyType = generator.GenerateProxyType(); return((T)Activator.CreateInstance(proxyType, target, decoration)); }
private T1 CreateProxy <T1, T2>(T1 target, InterceptorDelegate interceptor, Expression <Func <T1, T2> > propertyAccessor) { var property = (PropertyInfo)((MemberExpression)propertyAccessor.Body).Member; var propertyBasedInterceptor = new PropertyBasedInterceptorDecoration(property, interceptor, interceptor); var decoration = new InterceptorDecoration(null, new PropertyBasedInterceptorDecoration[] { propertyBasedInterceptor }); var generator = DynamicProxyClassGenerator.CreateInterfaceGenerator(typeof(T1), decoration); var proxyType = generator.GenerateProxyType(); return((T1)Activator.CreateInstance(proxyType, target, decoration)); }
public void TestGenericType() { //Foobar<T>() string flag = ""; InterceptorDelegate interceptor = next => (context => { flag = "Foobar"; return(next(context)); }); var proxy = this.CreateProxy <ICalculator <int> >(new IntCalculator(), interceptor, _ => _.Add(0, 0)); Assert.Equal(3, proxy.Add(1, 2)); Assert.Equal("Foobar", flag); }
public void TestGenericMethod() { var method = typeof(Calculator).GetMethod("Multiply"); string flag = ""; InterceptorDelegate interceptor = next => (context => { flag = "Foobar"; return(next(context)); }); var decoration = new InterceptorDecoration(new MethodBasedInterceptorDecoration[] { new MethodBasedInterceptorDecoration(method, interceptor) }, null); var proxy = this.CreateProxy <Calculator>(interceptor, typeof(Calculator).GetMethod("Multiply")); Assert.Equal(2, proxy.Multiply(1, 2)); Assert.Equal("Foobar", flag); }
private T CreateProxy <T>(InterceptorDelegate interceptor, MethodInfo method) { var methodBasedInterceptor = new MethodBasedInterceptorDecoration(method, interceptor); var decoration = new InterceptorDecoration(new MethodBasedInterceptorDecoration[] { methodBasedInterceptor }, null); var generator = DynamicProxyClassGenerator.CreateVirtualMethodGenerator(typeof(T), decoration); var proxyType = generator.GenerateProxyType(); var proxy = (T)Activator.CreateInstance(proxyType); ((IInterceptorsInitializer)proxy).SetInterceptors(decoration); return(proxy); }
private T1 CreateProxy <T1, T2>(InterceptorDelegate interceptor, Expression <Func <T1, T2> > propertyAccessor) { var property = (PropertyInfo)((MemberExpression)propertyAccessor.Body).Member; var propertyBasedInterceptor = new PropertyBasedInterceptorDecoration(property, interceptor, interceptor); var decoration = new InterceptorDecoration(null, new PropertyBasedInterceptorDecoration[] { propertyBasedInterceptor }); var generator = DynamicProxyClassGenerator.CreateVirtualMethodGenerator(typeof(T1), decoration); var proxyType = generator.GenerateProxyType(); var proxy = (T1)Activator.CreateInstance(proxyType); ((IInterceptorsInitializer)proxy).SetInterceptors(decoration); return(proxy); }
public void TestProperty() { string flag = ""; InterceptorDelegate interceptor = next => (context => { flag = "Foobar"; return(next(context)); }); var proxy = this.CreateProxy <DataAccessor, string>(interceptor, _ => _.Data); Assert.Equal("Foobar", proxy.Data); flag = ""; proxy.Data = "123"; Assert.Equal("Foobar", flag); }
public void TestIndex() { string flag = ""; InterceptorDelegate interceptor = next => (context => { flag = "Foobar"; return(next(context)); }); var proxy = this.CreateProxy <IDataAccessor>(new DataAccessor(), interceptor, typeof(IDataAccessor).GetProperty("Item", typeof(string)).GetMethod); Assert.Equal("Foobar", proxy[0]); Assert.Equal("Foobar", flag); flag = ""; proxy = this.CreateProxy <IDataAccessor>(new DataAccessor(), interceptor, typeof(IDataAccessor).GetProperty("Item", typeof(string)).SetMethod); proxy[0] = "abc"; Assert.Equal("Foobar", flag); }
/// <summary> /// Invoke interceptor and target method. /// </summary> /// <param name="interceptor">A <see cref="InterceptorDelegate"/> representing interceptor applied to target method.</param> /// <param name="handler">A <see cref="InterceptDelegate"/> used to invoke the target method.</param> /// <param name="context">A <see cref="InvocationContext"/> representing the current method invocation context.</param> /// <returns>The task to invoke interceptor and target method.</returns> public static Task InvokeHandler(InterceptorDelegate interceptor, InterceptDelegate handler, InvocationContext context) { InterceptDelegate wrapper = async _ => { await handler(_); var task = _.ReturnValue as Task; if (null != task) { await task; } }; var resultTask = interceptor(wrapper)(context); // throw inner InterceptorException var agregateException = resultTask.Exception; if (agregateException != null && agregateException.InnerExceptions.Any(ex => (ex is InterceptorException) && (ex as InterceptorException).RequireThrow)) { throw resultTask.Exception; } return(resultTask); }
public InterceptorDelegate Build() { var interceptors = this._interceptors.OrderByDescending(p => p.Key).Select(p => p.Value); InterceptorDelegate intercept = _next => { var current = _next; foreach (var item in interceptors) { current = item(current); } return(current); }; return(intercept); }
/// <summary> /// Add a new interceptor to interceptor chain. /// </summary> /// <param name="builder">The interceptor builder.</param> /// <param name="interceptorType">The type of interceptor.</param> /// <param name="order">The order to determine the position in the interceptor chain.</param> /// <param name="arguments">The arguments passed to constructor.</param> /// <returns>The current interceptor builder.</returns> /// <exception cref="ArgumentNullException">The specified <paramref name="builder"/> is null.</exception> /// <exception cref="ArgumentNullException">The specified <paramref name="interceptorType"/> is null.</exception> /// <exception cref="ArgumentException">The specified <paramref name="interceptorType"/> is not a valid interceptor. /// <para>The valid interceptor class should be defined as below.</para> /// <code> /// public class FoobarInterceptor /// { /// private InterceptDelegate _next; /// private IFoo _foo; /// /// public FoobarInterceptor(InterceptDelegate next, IFoo foo) /// { /// _next = next; /// _foo = foo; /// } /// /// public Task InvokeAsync(InvocationContext context, IBar bar) /// { /// ... /// await _next(context); /// } /// } /// </code> /// </exception> public static IInterceptorBuilder Use(this IInterceptorBuilder builder, Type interceptorType, int order, params object[] arguments) { Guard.ArgumentNotNull(builder, "builder"); Guard.ArgumentNotNull(interceptorType, "interceptorType"); InterceptorDelegate interceptor = next => (async context => { object[] newArguments = new object[arguments.Length + 1]; newArguments[0] = next; arguments.CopyTo(newArguments, 1); object instance = ActivatorUtilities.CreateInstance(builder.ServiceProvider, interceptorType, newArguments); InvokeDelegate factory = GetFactory(interceptorType); await factory(instance, context, builder.ServiceProvider); }); return(builder.Use(interceptor, order)); }
/// <summary> /// Method used to register an interceptor with Wsp. Only one interceptor is permitted. /// </summary> /// <param name="direction">Defines the direction the interceptor is registering for: publish or subscribe</param> /// <param name="interceptor">Delegate which Wsp will call for interception</param> /// <param name="onNextPrivate">Delegate to publish events which bypass interceptor logic</param> /// <returns>Guid needed to unregister</returns> public static Guid Register(InterceptDirection direction, InterceptorDelegate interceptor, out OnNextPrivate onNextPrivate) { WspEventPublish eventPublish = new WspEventPublish(); onNextPrivate = eventPublish.OnNextPrivate; if (direction != InterceptDirection.Publish && direction != InterceptDirection.Subscribe) { onNextPrivate = null; return(Guid.Empty); } if (direction == InterceptDirection.Subscribe) { if (subscribeRegistrationGuid == Guid.Empty) { subscribeInterceptor = interceptor; subscribeRegistrationGuid = Guid.NewGuid(); return(subscribeRegistrationGuid); } else { onNextPrivate = null; return(Guid.Empty); } } else { if (publishRegistrationGuid == Guid.Empty) { publishInterceptor = interceptor; publishRegistrationGuid = Guid.NewGuid(); return(publishRegistrationGuid); } else { onNextPrivate = null; return(Guid.Empty); } } }
public InterceptorChainBuilder Use(Type interceptorType, int order, params object[] args) { var invokeMethod = interceptorType.GetMethods().Where(p => p.Name == "InvokeAsync" && p.ReturnType == typeof(Task) && p.GetParameters().FirstOrDefault()?.ParameterType == typeof(InvocationContext)).FirstOrDefault(); if (invokeMethod == null) { return(this); } //InvokeDelegate(object interceptor, InvocationContext context, IServiceProvider serviceProvider); ParameterExpression interceptor = Expression.Parameter(typeof(object), "interceptor"); ParameterExpression context = Expression.Parameter(typeof(InvocationContext), "context"); ParameterExpression serviceProvider = Expression.Parameter(typeof(IServiceProvider), "serviceProvider"); var invArgs = invokeMethod.GetParameters().Select(p => { if (p.ParameterType == typeof(InvocationContext)) { return((Expression)context); } Expression serviceType = Expression.Constant(p.ParameterType, typeof(Type)); Expression callGetService = Expression.Call(_getServiceMethod, serviceProvider, serviceType); return((Expression)Expression.Convert(callGetService, p.ParameterType)); }); Expression instanceConvert = Expression.Convert(interceptor, interceptorType); var invoke = Expression.Call(instanceConvert, invokeMethod, invArgs); var invoker = Expression.Lambda <InvokeDelegate>(invoke, interceptor, context, serviceProvider).Compile(); InterceptorDelegate interceptorDelegate = _next => { var instance = ActivatorUtilities.CreateInstance(this.ServiceProvider, interceptorType, _next); InterceptDelegate _ = async invContext => { await invoker(instance, invContext, this.ServiceProvider); }; return(_); }; this._interceptors.Add(order, interceptorDelegate); return(this); }
public void Intercept(IInvocation invocation) { CastleInvocationContext invocationContext = new CastleInvocationContext(invocation, _serviceProvider); InterceptDelegate next = context => ((CastleInvocationContext)context).ProceedAsync(); try { _interceptor(next)(invocationContext).Wait(); } catch (AggregateException ex) { throw ex?.InnerException ?? ex; } catch { throw; } }
private InterceptorDecoration GetInterceptors(Type typeToIntercept, Dictionary <MethodInfo, IInterceptorProvider[]> providers) { var methodBasedDecorations = new List <MethodBasedInterceptorDecoration>(); var propertyBasedDecorations = new List <PropertyBasedInterceptorDecoration>(); foreach (var methodInfo in typeToIntercept.GetTypeInfo().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (methodInfo.IsSpecialName || methodInfo.DeclaringType == typeof(object)) { continue; } if (!providers.TryGetValue(methodInfo, out var methodProviders)) { continue; } var intercecptor = this.BuildInterceptor(methodProviders); methodBasedDecorations.Add(new MethodBasedInterceptorDecoration(methodInfo, intercecptor)); } foreach (var property in typeToIntercept.GetTypeInfo().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { InterceptorDelegate interceptorOfGetMethod = null; InterceptorDelegate interceptorOfSetMethod = null; var getMethod = property.GetMethod; var setMethod = property.SetMethod; if (null != getMethod && providers.TryGetValue(getMethod, out var getMethodProviders)) { interceptorOfGetMethod = this.BuildInterceptor(getMethodProviders); } if (null != setMethod && providers.TryGetValue(setMethod, out var setMethodProviders)) { interceptorOfSetMethod = this.BuildInterceptor(setMethodProviders); } if (null != interceptorOfGetMethod || null != interceptorOfSetMethod) { propertyBasedDecorations.Add(new PropertyBasedInterceptorDecoration(property, interceptorOfGetMethod, interceptorOfSetMethod)); } } return(new InterceptorDecoration(methodBasedDecorations, propertyBasedDecorations)); }
public static IInterceptorChainBuilder Use(this IInterceptorChainBuilder builder, Type interceptorType, int order, params object[] arguments) { InterceptorDelegate interceptor = next => (async context => { object[] newArguments = new object[arguments.Length + 1]; newArguments[0] = next; arguments.CopyTo(newArguments, 1); object instance = ActivatorUtilities.CreateInstance(builder.ServiceProvider, interceptorType, newArguments); InvokeDelegate invoker; if (TryGetInvoke(interceptorType, out invoker)) { await invoker(instance, context, builder.ServiceProvider); } else { throw new ArgumentException("Invalid interceptor type", "interceptorType"); } }); return(builder.Use(interceptor, order)); }
public void TestParameterType() { //General string flag = ""; InterceptorDelegate interceptor = next => (context => { flag = "Foobar"; return(next(context)); }); var proxy = this.CreateProxy <ICalculator>(new Calculator(), interceptor, _ => _.Add(0, 0)); Assert.Equal(3, proxy.Add(1, 2)); Assert.Equal("Foobar", flag); //ref, out double x = 1; double y = 2; double result; flag = ""; proxy = this.CreateProxy <ICalculator>(new Calculator(), interceptor, _ => _.Substract(ref x, ref y, out result)); proxy.Substract(ref x, ref y, out result); Assert.Equal(-1, result); }
public async void TestReturnType() { //Void string flag1 = ""; string flag2 = ""; InterceptorDelegate interceptor = next => (context => { flag1 = "Foobar"; return(next(context)); }); var proxy = this.CreateProxy <Foobar>(interceptor, _ => _.Invoke1()); proxy.Action = () => flag2 = "Foobar"; proxy.Invoke1(); Assert.Equal("Foobar", flag1); Assert.Equal("Foobar", flag2); //String flag1 = ""; flag2 = ""; proxy = this.CreateProxy <Foobar>(interceptor, _ => _.Invoke2()); proxy.Action = () => flag2 = "Foobar"; Assert.Equal("Foobar", proxy.Invoke2()); Assert.Equal("Foobar", flag1); Assert.Equal("Foobar", flag2); //Task flag1 = ""; flag2 = ""; proxy = this.CreateProxy <Foobar>(interceptor, _ => _.Invoke3()); proxy.Action = () => flag2 = "Foobar"; await proxy.Invoke3(); Assert.Equal("Foobar", flag1); Assert.Equal("Foobar", flag2); //Task<T> flag1 = ""; flag2 = ""; proxy = this.CreateProxy <Foobar>(interceptor, _ => _.Invoke4()); proxy.Action = () => flag2 = "Foobar"; Assert.Equal("Foobar", await proxy.Invoke4()); Assert.Equal("Foobar", flag1); Assert.Equal("Foobar", flag2); }
public TResult Invoke <TResult>(InterceptorDelegate interceptor, InvocationContext context) { Task task = null; if (_collections.TryGetValue(context.Method, out InterceptorMiddleware middleware)) { task = middleware(interceptor)(context); } else { task = interceptor(context); } if (task.IsFaulted) { throw task.Exception.InnerException; } if (!task.IsCompleted) { NoSyncContextScope.Run(task); } return((TResult)context.Return); }