Пример #1
0
 /// <summary>
 /// Invokes the OnEntry method on all elements of the aspect chain.
 /// </summary>
 /// <param name="aspects">Aspect chain</param>
 /// <param name="args">Method arguments descriptor</param>
 /// <returns>Result of the execution</returns>
 // ReSharper disable ParameterTypeCanBeEnumerable.Local
 private static IMethodResultDescriptor OnEntry(AspectChain aspects, IMethodCallDescriptor args)
 // ReSharper restore ParameterTypeCanBeEnumerable.Local
 {
     try
     {
         if (aspects == null)
         {
             return(null);
         }
         IMethodResultDescriptor result = null;
         foreach (var aspect in aspects)
         {
             result = aspect.OnEntry(args, null);
             if (result != null)
             {
                 break;
             }
         }
         return(result);
     }
     catch (Exception ex)
     {
         throw new AspectInfrastructureException(
                   "Aspect infrastructure exception caught in OnEntry", ex);
     }
 }
Пример #2
0
        /// <summary>
        /// Creates an intercepted object for the specified target using the provided aspect chain.
        /// </summary>
        /// <param name="serviceType">Type of service object</param>
        /// <param name="target">Target object to create an intercepted object for</param>
        /// <param name="aspects">Aspects to be used for the service object's method calls</param>
        /// <returns>Intercepted service object</returns>
        public static object GetInterceptedObject(Type serviceType, object target, AspectChain aspects)
        {
            if (serviceType == null)
            {
                throw new ArgumentNullException("serviceType");
            }

            // --- Check the cache
            InterceptedTypeDescriptor interceptor;

            if (!s_Interceptors.TryGetValue(serviceType, out interceptor))
            {
                lock (s_Interceptors)
                {
                    // --- Validate again to prevent a parallel type creation
                    if (!s_Interceptors.TryGetValue(serviceType, out interceptor))
                    {
                        // --- Validate input parameters
                        if (target == null)
                        {
                            throw new ArgumentNullException("target");
                        }
                        if (!serviceType.IsInterface || !serviceType.IsInstanceOfType(target))
                        {
                            throw new InvalidOperationException("Service type must be an interface" +
                                                                " type and the target object must implement that interface.");
                        }

                        // --- No generics is accepted
                        if (serviceType.IsGenericType ||
                            serviceType.GetMethods().Any(met => met.IsGenericMethod) ||
                            serviceType.GetInterfaces().Any(intf => intf.IsGenericType ||
                                                            intf.GetMethods().Any(met => met.IsGenericMethod)))
                        {
                            throw new InvalidOperationException(
                                      "Service type must not have generic parameters or methods.");
                        }

                        // --- We do not have any wrapper types for the specified service type
                        // --- Generate the interceptor type and save it in the cache
                        interceptor = new InterceptedTypeDescriptor
                        {
                            InterceptedType = serviceType,
                            Methods         = GetInterfaceMethods(serviceType)
                        };
                        GenerateWrappedType(interceptor, serviceType);
                        s_Interceptors[serviceType] = interceptor;
                    }
                }
            }

            // --- Instantiate the wrapped type
            var wrappedInstance = Activator.CreateInstance(
                interceptor.WrapperType,
                new[] { target, aspects });

            return(wrappedInstance);
        }
Пример #3
0
 /// <summary>
 /// Checks whether two aspect chains are equal.
 /// </summary>
 /// <param name="other">The other aspect chain to check for equality</param>
 protected bool Equals(AspectChain other)
 {
     if (_aspects.Count != other._aspects.Count)
     {
         return(false);
     }
     return(!_aspects.Where((t, i) => !t.Equals(other._aspects[i]) &&
                            !ReferenceEquals(t, other._aspects[i])).Any());
 }
Пример #4
0
 /// <summary>
 /// Invokes the OnException method on all elements of the aspect chain.
 /// </summary>
 /// <param name="aspects">Aspect chain</param>
 /// <param name="args">Method arguments descriptor</param>
 /// <param name="ex">Exception instance</param>
 /// <returns>Result of the execution</returns>
 private static Exception OnException(AspectChain aspects, IMethodCallDescriptor args,
                                      Exception ex)
 {
     try
     {
         return(aspects == null
                    ? ex
                    : aspects.Reverse.Aggregate(ex,
                                                (current, aspect) => aspect.OnException(args, current)));
     }
     catch (Exception newEx)
     {
         throw new AspectInfrastructureException(
                   "Aspect infrastructure exception caught in OnSuccess", newEx);
     }
 }
Пример #5
0
 /// <summary>
 /// Invokes the OnSuccess method on all elements of the aspect chain.
 /// </summary>
 /// <param name="aspects">Aspect chain</param>
 /// <param name="args">Method arguments descriptor</param>
 /// <param name="result">Result of the method call</param>
 /// <returns>Result of the execution</returns>
 private static IMethodResultDescriptor OnSuccess(AspectChain aspects, IMethodCallDescriptor args,
                                                  IMethodResultDescriptor result)
 {
     try
     {
         if (aspects != null)
         {
             foreach (var aspect in aspects.Reverse)
             {
                 aspect.OnSuccess(args, result);
             }
         }
         return(result);
     }
     catch (Exception ex)
     {
         throw new AspectInfrastructureException(
                   "Aspect infrastructure exception caught in OnSuccess", ex);
     }
 }
Пример #6
0
 /// <summary>
 /// Invokes the OnExit method on all elements of the aspect chain.
 /// </summary>
 /// <param name="aspects">Aspect chain</param>
 /// <param name="args">Method arguments descriptor</param>
 /// <param name="result">Result of the method call</param>
 /// <returns>Result of the execution</returns>
 private static void OnExit(AspectChain aspects, IMethodCallDescriptor args,
                            IMethodResultDescriptor result)
 {
     try
     {
         if (aspects == null)
         {
             return;
         }
         foreach (var aspect in aspects.Reverse)
         {
             aspect.OnExit(args, result);
         }
     }
     catch (Exception ex)
     {
         throw new AspectInfrastructureException(
                   "Aspect infrastructure exception caught in OnExit", ex);
     }
 }
Пример #7
0
 /// <summary>
 /// Creates an intercepted object for the specified target using the provided aspect chain.
 /// </summary>
 /// <typeparam name="TService">Type of service object</typeparam>
 /// <param name="target">Target object to create an intercepted object for</param>
 /// <param name="aspects">Aspects to be used for the service object's method calls</param>
 /// <returns>Intercepted service object</returns>
 public static TService GetInterceptedObject <TService>(TService target, AspectChain aspects)
 {
     return((TService)GetInterceptedObject(typeof(TService), target, aspects));
 }
Пример #8
0
        /// <summary>
        /// Executes the method call on the target object and wraps it into the execution of the
        /// specified object chain.
        /// </summary>
        /// <param name="target">Target object</param>
        /// <param name="arguments">Method call arguments</param>
        /// <param name="targetMethod"></param>
        /// <param name="aspects">Aspect chain to execute</param>
        /// <param name="methodInfo"></param>
        /// <returns>Result of the method execution</returns>
        public static IMethodResultDescriptor ExecuteWrappedCall <TService>(TService target, List <MethodArgument> arguments,
                                                                            MethodInfo methodInfo, Func <IMethodCallDescriptor, TService, IMethodResultDescriptor> targetMethod,
                                                                            AspectChain aspects)
        {
            // --- Use the aspects of the object, if that supports IMethodAspect
            if (aspects == null)
            {
                var typeAspects = GetAspects(methodInfo, target.GetType());
                if (typeAspects.Count > 0)
                {
                    aspects = new AspectChain(typeAspects);
                }
            }

            var targetAspect = target as IMethodAspect;

            if (targetAspect != null)
            {
                var aspectList = new List <IMethodAspect> {
                    targetAspect
                };
                if (aspects != null)
                {
                    aspectList.AddRange(aspects);
                }
                aspects = new AspectChain(aspectList);
            }

            // --- Obtain the method descriptor
            var args          = new MethodCallDescriptor(target, methodInfo, arguments);
            var onEntryResult = OnEntry(aspects, args);

            if (onEntryResult == null)
            {
                // --- Call original method body
                IMethodResultDescriptor result;
                try
                {
                    result = targetMethod(args, target);
                }
                catch (Exception ex)
                {
                    result = new MethodResultDescriptor(ex);
                }

                // --- Call OnExit
                OnExit(aspects, args, result);
                if (result.Exception == null)
                {
                    onEntryResult = OnSuccess(aspects, args, result);
                }
                else
                {
                    var newEx = OnException(aspects, args, result.Exception);
                    if (newEx == null)
                    {
                        throw new AspectInfrastructureException("OnException returned null.", null);
                    }
                    throw newEx;
                }
            }
            return(onEntryResult);
        }