コード例 #1
0
        public IInvocationPipelineExecutor CreateExecutor(IInvocationSignature signature)
        {
            if (_cache.IsAsync(signature.TargetMethod))
            {
                return(new AsyncInvocationPipelineExecutor(_cacheFactory));
            }

            return(InvocationPipelineExecutor.Instance);
        }
コード例 #2
0
        /// <inheritdoc />
        public MethodBoundaryAspect[] CreateBoundaryAspects(IInvocationSignature signature)
        {
            if (_aspectDeclarationCollector == null)
            {
                _aspectDeclarationCollector = _aspectDeclarationCollectorHolder.Get();
            }

            if (_aspectOrderStrategy == null)
            {
                _aspectOrderStrategy = _orderStrategyHolder.Get();
            }

            if (_aspectFinalizer == null)
            {
                _aspectFinalizer = _aspectFinalizerHolder.Get();
            }

            if (_dependencySelector == null)
            {
                _dependencySelector = _dependencySelectorHolder.Get();
            }

            var methodBoundaryAspects = new List <MethodBoundaryAspect>();
            var declarations          = _aspectDeclarationCollector.CollectAspectDeclarations <MethodBoundaryAspect>(signature);

            foreach (var aspect in _aspectOrderStrategy.Order(declarations.Select(d => d.MethodAspect)))
            {
                var existingAspect = methodBoundaryAspects.Find(aspect.Equals);

                // Если у текущего аспекта приоритет выше, чем равного тому,
                // что уже есть в коллекции, то заменяем его на новый
                if (existingAspect != null && aspect.Order < existingAspect.Order)
                {
                    methodBoundaryAspects.Remove(existingAspect);
                }
                else if (existingAspect == null)
                {
                    methodBoundaryAspects.Add(aspect);
                }
            }

            for (var i = 0; i < methodBoundaryAspects.Count; i++)
            {
                var currentAspect = methodBoundaryAspects[i];

                currentAspect.InternalOrder   = currentAspect.Order + i + 1;
                currentAspect.InternalId      = Guid.NewGuid();
                currentAspect.HasDependencies = _dependencySelector.HasDependencies(currentAspect.GetType());
                currentAspect.IsFinalizable   = _aspectFinalizer.IsFinalizable(currentAspect);
                currentAspect.IsInitializable = ReflectedMethod.IsOverriden(
                    MethodAspect.GetInitializeMethod(currentAspect));
            }

            return(methodBoundaryAspects.ToArray());
        }
コード例 #3
0
        public IInvocationPipeline CreatePipeline(
            IInvocationSignature signature,
            MethodBoundaryAspect[] boundaryAspects,
            MethodInterceptionAspect interceptionAspect)
        {
            if (_cache.IsAsync(signature.TargetMethod))
            {
                return(new AsyncInvocationPipeline(signature, boundaryAspects, interceptionAspect));
            }

            return(new InvocationPipeline(signature, boundaryAspects, interceptionAspect));
        }
コード例 #4
0
        /// <summary>
        /// Инициализирует экземпляр <see cref="AsyncInvocationPipeline"/>.
        /// </summary>
        public AsyncInvocationPipeline(
            IInvocationSignature signature,
            IReadOnlyCollection <MethodBoundaryAspect> boundaryAspects,
            MethodInterceptionAspect interceptionAspect)
            : base(signature, boundaryAspects, interceptionAspect)
        {
            ReturnTypeInner = signature.InvocationType == InvocationType.AsyncFunction
                ? signature.Method.ReturnType.GetGenericArguments()[0]
                : null;

            CanReturnValue             = ReturnTypeInner != null;
            DefaultReturnValueProvider = new Lazy <object>(() => ReturnTypeInner != null
                ? ReturnTypeInner.GetDefaultValue()
                : null);
        }
コード例 #5
0
        private static MethodCall GetAsyncFunctionHandler(
            IKeyValueCache <Type, MethodCall> cache,
            IInvocationSignature signature)
        {
            var innerType = signature.Method.ReturnType.GetGenericArguments()[0];

            return(cache.GetOrAdd(innerType, key =>
            {
                var method = typeof(AsyncInvocationPipelineExecutor)
                             .GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)
                             .First(m => m.IsGenericMethodDefinition && m.Name == nameof(SignalWhenAwait))
                             .MakeGenericMethod(innerType);

                return Expressions.CreateMethodCall(method);
            }));
        }
コード例 #6
0
        /// <inheritdoc />
        public override bool IsWeaveable(IInvocationSignature signature)
        {
            if (!signature.DeclaringType.IsInterface)
            {
                return(false);
            }

            if (IsWeavingSuppressed(signature.Method))
            {
                return(false);
            }

            var selector = AspectSelectorHolder.Get();

            return(selector.HasAnyAspect(signature.Method) ||
                   IsWeaveable(signature.DeclaringType, signature.TargetType));
        }
コード例 #7
0
        /// <inheritdoc />
        public IEnumerable <MethodAspectDeclaration <TAspect> > CollectAspectDeclarations <TAspect>(
            IInvocationSignature signature) where TAspect : MethodAspect
        {
            var selector = _selectorHolder.Get();

            var methodAspectDeclarations = selector.SelectAspectDeclarations <TAspect>(signature.TargetMethod);

            var typeAspectDeclarations = selector.SelectAspectDeclarations <TAspect>(signature.TargetType)
                                         .Concat(signature.TargetType.GetInterceptableBaseTypes()
                                                 .SelectMany(t => selector.SelectAspectDeclarations <TAspect>(t)));

            var aspectDeclarations = typeAspectDeclarations
                                     .Concat(methodAspectDeclarations)
                                     .Where(m => m.MethodAspect != null &&
                                            m.MulticastTarget != MethodAspectMulticastTarget.Undefined);

            return(aspectDeclarations);
        }
コード例 #8
0
        /// <inheritdoc />
        public MethodInterceptionAspect CreateInterceptAspect(IInvocationSignature context)
        {
            if (_aspectDeclarationCollector == null)
            {
                _aspectDeclarationCollector = _aspectDeclarationCollectorHolder.Get();
            }

            if (_aspectFinalizer == null)
            {
                _aspectFinalizer = _aspectFinalizerHolder.Get();
            }

            var aspectDeclarations = _aspectDeclarationCollector
                                     .CollectAspectDeclarations <MethodInterceptionAspect>(context)
                                     .ToArray();

            if (aspectDeclarations.Length > 1)
            {
                throw new IvorySharpException(
                          $"Допустимо наличие только одного аспекта типа '{typeof(MethodInterceptionAspect)}'. " +
                          $"На методе '{context.Method.Name}' типа '{context.DeclaringType.FullName}' задано несколько.");
            }

            if (aspectDeclarations.Length == 0)
            {
                return(BypassMethodAspect.Instance);
            }

            if (_dependencySelector == null)
            {
                _dependencySelector = _dependencySelectorHolder.Get();
            }

            var declaration = aspectDeclarations.Single();

            declaration.MethodAspect.MulticastTarget = declaration.MulticastTarget;
            declaration.MethodAspect.InternalId      = Guid.NewGuid();
            declaration.MethodAspect.HasDependencies = _dependencySelector.HasDependencies(declaration.MethodAspect.GetType());
            declaration.MethodAspect.IsFinalizable   = _aspectFinalizer.IsFinalizable(declaration.MethodAspect);
            declaration.MethodAspect.IsInitializable = ReflectedMethod.IsOverriden(
                MethodAspect.GetInitializeMethod(declaration.MethodAspect));

            return(declaration.MethodAspect);
        }
コード例 #9
0
        /// <inheritdoc />
        public IEnumerable <MethodAspectDeclaration <TAspect> > CollectAspectDeclarations <TAspect>(
            IInvocationSignature signature) where TAspect : MethodAspect
        {
            if (_aspectSelector == null)
            {
                _aspectSelector = _aspectSelectorHolder.Get();
            }

            var methodAspectDeclarations = _aspectSelector.SelectAspectDeclarations <TAspect>(signature.Method);
            var typeAspectDeclarations   = _aspectSelector.SelectAspectDeclarations <TAspect>(signature.DeclaringType)
                                           .Concat(signature.DeclaringType.GetInterceptableInterfaces()
                                                   .SelectMany(i => _aspectSelector.SelectAspectDeclarations <TAspect>(i)));

            var aspectDeclarations = typeAspectDeclarations
                                     .Concat(methodAspectDeclarations)
                                     .Where(m => m.MethodAspect != null &&
                                            m.MulticastTarget != MethodAspectMulticastTarget.Undefined);

            return(aspectDeclarations);
        }
コード例 #10
0
 /// <inheritdoc />
 public abstract bool IsWeaveable([NotNull]  IInvocationSignature signature);
コード例 #11
0
 /// <inheritdoc />
 public InvocationWeaveData Get(IInvocationSignature signature)
 {
     return(_data.TryGetValue(signature, out var data) ? data : null);
 }
コード例 #12
0
        /// <summary>
        /// Выполняет перехват вызова исходного метода с применением аспектов.
        /// </summary>
        /// <param name="signature">Сигнатура метода.</param>
        /// <param name="methodCall">Делегат вызова метода.</param>
        /// <param name="args">Параметры вызова метода.</param>
        /// <param name="target">Экземпляр сервиса.</param>
        /// <param name="proxy">Прокси сервиса.</param>
        /// <returns>Результат вызова метода.</returns>
        internal object Intercept(
            IInvocationSignature signature, MethodCall methodCall,
            object[] args, object target, object proxy)
        {
            var invocationData = _weaveDataProvider.Get(signature);

            if (invocationData == null)
            {
                throw new IvorySharpException(
                          $"Не найдена информация о вызываемом методе '{signature.Method.Name}'. " +
                          $"DeclaringType: {signature.DeclaringType.Name} " +
                          $"ImplementationType: {signature.TargetType.Name}");
            }

            if (!invocationData.IsWeaveable)
            {
                // Bypass
                return(methodCall(target, args));
            }

            var invocation = new Invocation(signature, args, proxy, target, methodCall);

            foreach (var aspect in invocationData.BoundaryAspects)
            {
                if (aspect.HasDependencies)
                {
                    _dependencyInjector.InjectPropertyDependencies(aspect);
                }

                if (aspect.IsInitializable)
                {
                    aspect.Initialize();
                }
            }

            if (invocationData.InterceptionAspect.HasDependencies)
            {
                _dependencyInjector.InjectPropertyDependencies(invocationData.InterceptionAspect);
            }

            if (invocationData.InterceptionAspect.IsInitializable)
            {
                invocationData.InterceptionAspect.Initialize();
            }

            invocationData.PipelineExecutor.ExecutePipeline(invocationData.Pipeline, invocation);

            foreach (var aspect in invocationData.BoundaryAspects)
            {
                if (aspect.IsFinalizable)
                {
                    _aspectFinalizer.Finalize(aspect);
                }
            }

            if (invocationData.InterceptionAspect.IsFinalizable)
            {
                _aspectFinalizer.Finalize(invocationData.InterceptionAspect);
            }

            return(invocation.ReturnValue);
        }