示例#1
0
        private static void BuildForSingleHandler(MiddlewareBuilderContext context)
        {
            // We only have a single handler, return the result of that
            var allHandlers = context.Descriptor.Handlers;
            var handler     = allHandlers.Single();

            var apmFrame = ActivityFrame.Start(ActivityKind.Internal, handler.HandlerType.NameInCode());

            context.AppendFrames(apmFrame);

            var returnVariable = handler.Build(context, ExecutorReturnType.Return);

            if (returnVariable == null && context.Descriptor.RequiresReturnValue)
            {
                throw new InvalidOperationException(
                          $@"Unable to build an executor for the operation {context.Descriptor} because the single handler registered, {handler}, did not return a variable but the operation has {nameof(context.Descriptor.RequiresReturnValue)} set to true. 

This can happen if an the only registered handler for an operation is one that is NOT of the same type (for example a handler IApiOperationHandler<ConcreteClass> for the operation IOperationInterface) where it cannot be guaranteed that the handler will be executed.");
            }

            if (returnVariable != null)
            {
                returnVariable.OverrideName("handlerResult");

                context.AppendFrames(new OperationResultCastFrame(returnVariable));
            }

            context.AppendFrames(apmFrame.Complete());
        }
示例#2
0
        private static void BuildForMultipleHandlers(MiddlewareBuilderContext context)
        {
            if (context.Descriptor.RequiresReturnValue)
            {
                throw new InvalidOperationException(
                          $@"Unable to build an executor for the operation {context.Descriptor} because multiple handlers have been registered but the operation has {nameof(context.Descriptor.RequiresReturnValue)} set to true. 

When {nameof(context.Descriptor.RequiresReturnValue)} is true multiple handlers cannot be used as there is not one, obvious, return value that could be used.

Handlers found:
  - {string.Join("\n  - ", context.Descriptor.Handlers)}
");
            }

            foreach (var handler in context.Descriptor.Handlers)
            {
                var apmFrame = ActivityFrame.Start(ActivityKind.Internal, handler.HandlerType.NameInCode());
                context.AppendFrames(apmFrame);

                handler.Build(context, ExecutorReturnType.NoReturn);

                context.AppendFrames(apmFrame.Complete());
            }
        }
示例#3
0
        private void Generate(
            BlueprintApiOptions options,
            IServiceProvider serviceProvider,
            GeneratedMethod executeMethod,
            ApiOperationDescriptor operation,
            ApiDataModel model,
            IServiceScope serviceScope,
            bool isNested)
        {
            var operationContextVariable = executeMethod.Arguments[0];

            var instanceFrameProvider             = serviceProvider.GetRequiredService <InstanceFrameProvider>();
            var dependencyInjectionVariableSource = new DependencyInjectionVariableSource(executeMethod, instanceFrameProvider);

            var castFrame = new ConcreteOperationCastFrame(operationContextVariable, operation.OperationType);

            var apiOperationContextSource =
                new ApiOperationContextVariableSource(operationContextVariable, castFrame.CastOperationVariable);

            var context = new MiddlewareBuilderContext(
                executeMethod,
                operation,
                model,
                serviceScope.ServiceProvider,
                instanceFrameProvider,
                isNested);

            // For the base Exception type we will add, as the first step, logging to the exception sinks. This frame DOES NOT
            // include a return frame, as we add that after all the other middleware builders have had chance to potentially add
            // more frames to perform other operations on unknown Exception
            context.RegisterUnhandledExceptionHandler(typeof(Exception), e => new Frame[]
            {
                // Exceptions do not escape from a pipeline because we always convert to a result type
                new PushExceptionToActivityFrame(e, false),
            });

            executeMethod.Sources.Add(apiOperationContextSource);
            executeMethod.Sources.Add(dependencyInjectionVariableSource);

            foreach (var source in options.GenerationRules.VariableSources)
            {
                executeMethod.Sources.Add(source);
            }

            var startActivityFrame = ActivityFrame.Start(ActivityKind.Internal, operation.Name + (isNested ? "NestedPipeline" : "Pipeline"));

            executeMethod.Frames.Add(startActivityFrame);

            executeMethod.Frames.Add(castFrame);
            executeMethod.Frames.Add(new ErrorHandlerFrame(context));
            executeMethod.Frames.Add(new BlankLineFrame());

            foreach (var behaviour in this._builders)
            {
                if (isNested && !behaviour.SupportsNestedExecution)
                {
                    continue;
                }

                if (behaviour.Matches(operation))
                {
                    executeMethod.Frames.Add(new CommentFrame(behaviour.GetType().Name));

                    behaviour.Build(context);

                    executeMethod.Frames.Add(new BlankLineFrame());
                }
            }

            // For the base Exception type we will add, as a last frame, a return of an OperationResult.
            context.RegisterUnhandledExceptionHandler(typeof(Exception), e => new[]
            {
                new ReturnFrame(new Variable(typeof(UnhandledExceptionOperationResult), $"new {typeof(UnhandledExceptionOperationResult).FullNameInCode()}({e})")),
            });
        }