/// <inheritdoc /> public void Build(MiddlewareBuilderContext context) { var sources = context.ServiceProvider .GetServices <IMessagePopulationSource>() .OrderBy(s => s.Priority) .ToList(); var allOwned = new List <OwnedPropertyDescriptor>(); var ownedBySources = new Dictionary <IMessagePopulationSource, IReadOnlyCollection <OwnedPropertyDescriptor> >(); foreach (var s in sources) { var ownedBySource = s.GetOwnedProperties(context.Model, context.Descriptor).ToList(); ownedBySources[s] = ownedBySource; foreach (var p in ownedBySource) { if (allOwned.Contains(p)) { throw new InvalidOperationException( $"Property {p.Property.DeclaringType.Name}.{p.Property.Name} has been marked as owned by multiple sources. A property can only be owned by a single source."); } allOwned.Add(p); } } foreach (var s in sources) { s.Build(allOwned, ownedBySources[s], context); } }
/// <inheritdoc /> public void Build(MiddlewareBuilderContext context) { // Force the creation of the stopwatch variable to be at the very start of the method, ensures it // starts before _anything_ happens and makes it available to the finally block too context.ExecuteMethod.Frames.Insert(0, new LoggingStartFrame()); context.RegisterFinallyFrames(new LoggingEndFrame(context.Descriptor.OperationType)); }
/// <inheritdoc /> public void Build(MiddlewareBuilderContext context) { var getClaimsIdentityProvider = context.TryGetVariableFromContainer <IClaimsIdentityProvider>(); // A claims identity provider may not be registered, we can skip generation altogether if (getClaimsIdentityProvider == null) { return; } /* Generates: * if (context.ClaimsIdentity == null) * { * var claimsIdentity = GetInstance<IClaimsIdentityProvider>.Get(context); * context.ClaimsIdentity = claimsIdentity; * } */ var claimsIdentityVariable = context.FindVariable <ClaimsIdentity>(); var getClaimsIdentity = MethodCall.For <IClaimsIdentityProvider>(p => p.Get(null)); context.AppendFrames( new IfNullBlock(claimsIdentityVariable) { getClaimsIdentityProvider, getClaimsIdentity, new VariableSetterFrame(claimsIdentityVariable, getClaimsIdentity.ReturnVariable), }); }
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()); }
/// <inheritdoc /> public Variable Build(MiddlewareBuilderContext context, ExecutorReturnType executorReturnType) { // We rely on the compiler infrastructure to make the correct calls, to the correct type (i.e. the actual // operation), and to fill in the parameters of that method as required. var handlerInvokeCall = new MethodCall(context.Descriptor.OperationType, this._method) { IgnoreReturnVariable = executorReturnType == ExecutorReturnType.NoReturn, }; // Note that although we know the handler type at compile time, we still specify it as a // parameter to logging so that it is output as a structured value (as it changes between // invocations) context.AppendFrames( LogFrame.Debug( _apiOperationExecutorLogEvent, "Executing API operation {OperationType} with inline handler", ReflectionUtilities.PrettyTypeName(context.Descriptor.OperationType)), handlerInvokeCall); // We have a void, or a Task (i.e. async with no return) so we will convert to a 'NoResult' if (handlerInvokeCall.ReturnVariable == null || handlerInvokeCall.ReturnVariable.VariableType == typeof(Task)) { var emptyResultCreation = new VariableCreationFrame( typeof(NoResultOperationResult), $"{typeof(NoResultOperationResult).FullNameInCode()}.{nameof(NoResultOperationResult.Instance)};"); context.AppendFrames(emptyResultCreation); return(emptyResultCreation.CreatedVariable); } return(handlerInvokeCall.ReturnVariable); }
public void Build(MiddlewareBuilderContext context) { var getResourceEventRepository = context.VariableFromContainer <IResourceEventRepository>(); context.AppendFrames( getResourceEventRepository, new MethodCall(typeof(ResourceEventHandler), nameof(ResourceEventHandler.HandleAsync))); }
public void Build(MiddlewareBuilderContext context) { var getGenerators = context.VariableFromContainer <IEnumerable <IResourceLinkGenerator> >(); context.AppendFrames( getGenerators, new MethodCall(typeof(LinkGeneratorHandler), nameof(LinkGeneratorHandler.AddLinksAsync))); }
/// <inheritdoc /> public void Build(MiddlewareBuilderContext context) { if (context.Descriptor.RequiresReturnValue) { context.ExecuteMethod.Frames.Add(new ReturnFrame(typeof(OperationResult))); } else { context.ExecuteMethod.Frames.Add(new ReturnFrame(Variable.StaticFrom <NoResultOperationResult>(nameof(NoResultOperationResult.Instance)))); } }
/// <inheritdoc /> public void Build(MiddlewareBuilderContext context) { if (context.Descriptor.Handlers.Count > 1) { BuildForMultipleHandlers(context); } else { BuildForSingleHandler(context); } }
/// <inheritdoc /> public void Build(MiddlewareBuilderContext context) { var apmFrame = ApmSpanFrame.Start(SpanKinds.Internal, "Handler", "exec"); context.AppendFrames(apmFrame); if (context.Descriptor.Handlers.Count > 1) { 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) { handler.Build(context, ExecutorReturnType.NoReturn); } } else { // We only have a single handler, return the result of that var allHandlers = context.Descriptor.Handlers; var handler = allHandlers.Single(); 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()); }
/// <inheritdoc /> public Variable Build(MiddlewareBuilderContext context, ExecutorReturnType executorReturnType) { var getInstanceFrame = context.VariableFromContainer(this._iocServiceType); // We must look for the _exact_ method call that corresponds to the operation type as // we support handlers that implement multiple IApiOperationHandler<T> interfaces var handlerInvokeCall = new MethodCall( this._iocServiceType, this._iocServiceType.GetMethods().First(m => m.Name == nameof(IApiOperationHandler <object> .Handle))) { IgnoreReturnVariable = executorReturnType == ExecutorReturnType.NoReturn, }; var invocationFrames = new Frame[] { getInstanceFrame, LogFrame.Debug( _apiOperationExecutorLogEvent, "Executing API operation {OperationType} with handler {HandlerType}", ReflectionUtilities.PrettyTypeName(context.Descriptor.OperationType), new Variable(typeof(string), $"{getInstanceFrame.InstanceVariable}.GetType().Name")), handlerInvokeCall, }; // If it is not directly assignable then we need to do a runtime check and cast. This handles the case // of a concrete handler for an interface operation (i.e. operation is IGenericMessage and the handler // is IApiOperationHandler<ConcreteMessage> where ConcreteMessage : IGenericMessage) if (this._handledOperationType.IsAssignableFrom(this._operationType) == false) { var operationVariable = context.FindVariable(this._operationType); handlerInvokeCall.TrySetArgument(new CastVariable( operationVariable, this._handledOperationType)); context.AppendFrames( new IfBlock($"{operationVariable} is {this._handledOperationType.FullNameInCode()}", invocationFrames)); return(null); } // We are explicit about setting the operation argument as it may be that the operation type is not // exactly the same (inheritance) and would therefore not be found by the variable system handlerInvokeCall.Arguments[0] = context.FindVariable(this._operationType); context.AppendFrames(invocationFrames); return(handlerInvokeCall.ReturnVariable); }
public void Build(MiddlewareBuilderContext context) { context.AppendFrames(new MethodCall(this.GetType(), nameof(WriteSuccess))); context.RegisterUnhandledExceptionHandler(typeof(Exception), (e) => { var methodCall = new MethodCall(this.GetType(), nameof(WriteFailure)); methodCall.TrySetArgument(e); return(new[] { methodCall, }); }); }
public void Build(MiddlewareBuilderContext context) { var checkFrames = new List <Frame>(); // Generates: // // if (!context.SkipAuthorisation) // { // if (context.UserAuthorisationContext == null) // { // throw new SecurityException("Access denied. Anonymous access is not allowed."); // } // // foreach (authorisers) { await a.EnforceAsync(); } // } var authorisationContextVariable = context.FindVariable <IUserAuthorisationContext>(); checkFrames.Add( new IfBlock($"{authorisationContextVariable} == null") { new ThrowExceptionFrame <SecurityException>(AccessDeniedExceptionMessage), }); foreach (var checker in context.ServiceProvider.GetServices <IApiAuthoriser>()) { if (checker.AppliesTo(context.Descriptor)) { var getInstanceVariable = context.VariableFromContainer(checker.GetType()); var methodCall = new MethodCall(typeof(AuthorisationMiddlewareBuilder), nameof(EnforceAsync)); // HACK: We cannot set just by variable type as compiler fails with index out of range (believe this // is because the declared type is IApiAuthoriser but variable is subtype) methodCall.TrySetArgument("authoriser", getInstanceVariable.InstanceVariable); checkFrames.Add(getInstanceVariable); checkFrames.Add(methodCall); } } // We only run authorisation checks if SkipAuthorisation is false, which it will be by default context.AppendFrames( new IfBlock( $"{context.FindVariable<ApiOperationContext>()}.{nameof(ApiOperationContext.SkipAuthorisation)} == false", checkFrames.ToArray())); context.RegisterFinallyFrames(new SetApmUserDetailsFrame()); }
public void Build(MiddlewareBuilderContext context) { if (context.Descriptor.AnonymousAccessAllowed) { // TODO: Should we be loading user auth context even if anon access allowed as some may still use if available? // Generates // // context.UserAuthorisationContext = AnonymousUserAuthorisationContext.Instance; // When we allow anonymous just inject the AnonymousUserAuthorisationContext at all times (is this right?) context.AppendFrames( new VariableSetterFrame( context.FindVariable <IUserAuthorisationContext>(), Variable.StaticFrom <AnonymousUserAuthorisationContext>(nameof(AnonymousUserAuthorisationContext.Instance)))); } else { // Generates: // // if (context.ClaimsIdentity != null && context.ClaimsIdentity.IsAuthenticated == true) // { // var userSecurityContext = await this.userSecurityContextFactory.CreateContextAsync(context.ClaimsIdentity); // context.UserAuthorisationContext = userSecurityContext; // } var claimsIdentityVariable = context.FindVariable <ClaimsIdentity>(); var userSecurityContextFactoryCreator = context.VariableFromContainer <IUserAuthorisationContextFactory>(); var createContextCall = userSecurityContextFactoryCreator.Method(f => f.CreateContextAsync(null)); createContextCall.TrySetArgument(claimsIdentityVariable); context.AppendFrames( new IfBlock($"{claimsIdentityVariable} != null && {claimsIdentityVariable.GetProperty(nameof(ClaimsIdentity.IsAuthenticated))} == true") { userSecurityContextFactoryCreator, createContextCall, new VariableSetterFrame(context.FindVariable <IUserAuthorisationContext>(), createContextCall.ReturnVariable), }); } }
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()); } }
public void Build(MiddlewareBuilderContext context) { context.RegisterUnhandledExceptionHandler(exceptionType, create); }
/// <inheritdoc /> public void Build( IReadOnlyCollection <OwnedPropertyDescriptor> ownedProperties, IReadOnlyCollection <OwnedPropertyDescriptor> ownedBySource, MiddlewareBuilderContext context) { // We can bail early on any code generation as we know that all properties are fulfilled by // other sources if (ownedProperties.Count == context.Descriptor.Properties.Length && ownedBySource.Count == 0) { return; } if (context.Descriptor.TryGetFeatureData <HttpOperationFeatureData>(out var httpData) == false) { return; } if (ownedBySource.Count > 1) { throw new InvalidOperationException( $"Operation {context.Descriptor.OperationType} declares multiple properties with the {nameof(FromBodyAttribute)} which is not allowed. At most one property can be decorated with that attribute."); } // If the request method is a GET then there will be no body, and therefore we do not need to attempt to // read the message body at all. if (httpData.HttpMethod != "GET") { var operationVariable = context.FindVariable(context.Descriptor.OperationType); if (ownedBySource.Any()) { // We have [FromBody] so that needs to be set, instead of populating the context.Operation property. var prop = ownedBySource.Single(); var operationProperty = operationVariable.GetProperty(prop.Property.Name); var readCall = new MethodCall( typeof(HttpBodyMessagePopulationSource), _populateBodyMethod.MakeGenericMethod(operationProperty.VariableType)); readCall.TrySetArgument(new Variable(operationProperty.VariableType, $"new {operationProperty.VariableType.FullNameInCode()}()")); context.AppendFrames( readCall, new VariableSetterFrame(operationProperty, readCall.ReturnVariable)); } else { var readCall = new MethodCall( typeof(HttpBodyMessagePopulationSource), _populateBodyMethod.MakeGenericMethod(context.Descriptor.OperationType)); readCall.TrySetArgument(operationVariable); readCall.ReturnVariable.OverrideName("parseBodyResult"); var setInOperation = new VariableSetterFrame(operationVariable, readCall.ReturnVariable); var setAmbient = new VariableSetterFrame( context.FindVariable(typeof(ApiOperationContext)).GetProperty(nameof(ApiOperationContext.Operation)), readCall.ReturnVariable); context.AppendFrames( readCall, setInOperation, setAmbient); } } }
/// <summary> /// Initialises a new instance of the <see cref="PushToErrorLoggerExceptionCatchFrame" /> class. /// </summary> /// <param name="context">The builder context this frame belongs to.</param> /// <param name="exceptionVariable">The variable representing the <see cref="Exception" /> that has /// been raised.</param> public PushToErrorLoggerExceptionCatchFrame(MiddlewareBuilderContext context, Variable exceptionVariable) { this._context = context; this._exceptionVariable = exceptionVariable; }
/// <inheritdoc/> public void Build(MiddlewareBuilderContext context) { context.AppendFrames(new ConditionalFrame( (v, _) => v.TryFindVariable(typeof(OperationResult)) != null, new MethodCall(typeof(LinkGeneratorHandler), nameof(LinkGeneratorHandler.AddLinksAsync)))); }
/// <inheritdoc /> public void Build(MiddlewareBuilderContext context) { var properties = context.Descriptor.Properties; var operationVariable = context.FindVariable(context.Descriptor.OperationType); var apiOperationDescriptorVariable = context.FindVariable <ApiOperationDescriptor>(); var resultsCreator = new ConstructorFrame <ValidationFailures>(() => new ValidationFailures()); var hasValidationFrames = false; var sources = context.ServiceProvider.GetServices <IValidationSourceBuilder>(); void AddValidatorFrame(Frame frame) { if (!hasValidationFrames) { // Only add the "results creator" frame if there are any actual validation calls. This is the line // that creates an empty ValidationFailures context.ExecuteMethod.Frames.Add(resultsCreator); hasValidationFrames = true; } context.ExecuteMethod.Frames.Add(frame); } var operationProperties = new List <OperationProperty>(); for (var i = 0; i < properties.Length; i++) { var p = properties[i]; var propertyInfoVariable = new PropertyInfoVariable(p, $"{apiOperationDescriptorVariable}.{nameof(ApiOperationDescriptor.Properties)}[{i}]"); var propertyAttributesVariable = new Variable(typeof(object[]), $"{apiOperationDescriptorVariable}.{nameof(ApiOperationDescriptor.PropertyAttributes)}[{i}]"); var propertyValueVariable = operationVariable.GetProperty(p.Name); operationProperties.Add(new OperationProperty { PropertyInfoVariable = propertyInfoVariable, PropertyValueVariable = propertyValueVariable, PropertyAttributesVariable = propertyAttributesVariable, }); } foreach (var s in sources) { foreach (var frame in s.GetFrames(operationVariable, operationProperties)) { AddValidatorFrame(frame); } } // Only bother trying to validate if properties actually exist that are validated if (hasValidationFrames) { /* * var validationFailures = _from above_; * * if (validationFailures.Count > 0) * { * var validationResult = new ValidationResult(validationFailures); * * return validationResult; * } */ var createResult = new ConstructorFrame <ValidationFailedOperationResult>(() => new ValidationFailedOperationResult((ValidationFailures)null)); var failureCount = $"{resultsCreator.Variable}.{nameof(ValidationFailures.Count)}"; context.AppendFrames( new IfBlock($"{failureCount} > 0") { LogFrame.Debug( _validationFailedLogEvent, "Validation failed with {ValidationFailureCount} failures, returning ValidationFailedOperationResult", new Variable <int>(failureCount)), createResult, new ReturnFrame(createResult.Variable), }); } var apiOperationContext = context.FindVariable(typeof(ApiOperationContext)); var activityVariable = apiOperationContext.GetProperty(nameof(ApiOperationContext.Activity)); // Always need to register extra exception handlers because the operation handler itself may do additional validation // and throw an exception to indicate a problem, even if the operation itself is _not_ validated context.RegisterUnhandledExceptionHandler(typeof(ValidationException), e => RegisterBlueprintExceptionHandler(activityVariable, e)); context.RegisterUnhandledExceptionHandler(typeof(System.ComponentModel.DataAnnotations.ValidationException), e => RegisterDataAnnotationsExceptionHandler(activityVariable, e)); }
/// <inheritdoc /> public void Build( IReadOnlyCollection <OwnedPropertyDescriptor> ownedProperties, IReadOnlyCollection <OwnedPropertyDescriptor> ownedBySource, MiddlewareBuilderContext context) { if (context.Descriptor.TryGetFeatureData <HttpOperationFeatureData>(out var _) == false) { return; } var allLinks = context.Model.GetLinksForOperation(context.Descriptor.OperationType).ToList(); var placeholderProperties = allLinks .SelectMany(l => l.Placeholders) .Select(p => p.Property) .Distinct() .ToList(); var operationVariable = context.FindVariable(context.Descriptor.OperationType); // Add a single setter frame so we only grab using GetRouteData() once var routeDataFrame = new MethodCall(typeof(ApiOperationContextHttpExtensions), nameof(ApiOperationContextHttpExtensions.GetRouteData)); if (placeholderProperties.Any()) { context.ExecuteMethod.Frames.Add(routeDataFrame); } foreach (var routePropertyPlaceholder in placeholderProperties) { var routeProperty = routePropertyPlaceholder; if (routeProperty.PropertyType != typeof(string) && !TypeDescriptor.GetConverter(routeProperty.PropertyType).CanConvertFrom(typeof(string))) { throw new InvalidOperationException( $"Property {context.Descriptor.OperationType.Name}.{routeProperty.Name} cannot be used in routes, it cannot be converted from string"); } var operationProperty = operationVariable.GetProperty(routeProperty.Name); var routeValuesVariable = routeDataFrame.ReturnVariable.GetProperty(nameof(RouteData.Values)); // When this property is not in ALL routes we use TryGetValue from the RouteData dictionary and pass // the var output from that to `GetConversionExpression` as part of ternary. If the route data // does not exist then we fallback to the value already on the operation var outVariableName = "routeValue" + routeProperty.Name; var conversionExpression = HttpPartMessagePopulationSource.GetConversionExpression( routeProperty, outVariableName, false, "Route"); // context.RouteData.TryGetValue("PropertyName", out var routeValuePropertyName) ? [conversion of routeValuePropertyName] : [operationProperty]; var tryConversionExpression = $"{routeValuesVariable}.{nameof(RouteValueDictionary.TryGetValue)}(\"{routeProperty.Name}\", out var {outVariableName}) ? " + $"{conversionExpression} : " + $"{operationProperty}"; context.ExecuteMethod.Frames.Add(new VariableSetterFrame( operationProperty, tryConversionExpression)); } }
/// <summary> /// Initialises a new instance of the <see cref="SetTagsFromMessageDataFrame" /> class. /// </summary> /// <param name="context">The builder context this frame belongs to.</param> public SetTagsFromMessageDataFrame(MiddlewareBuilderContext context) { this._context = context; }
/// <summary> /// Initialises a new instance of the <see cref="ErrorHandlerFrame" /> class. /// </summary> /// <param name="context">The builder context for this frame.</param> public ErrorHandlerFrame(MiddlewareBuilderContext context) { this._context = context; }
/// <inheritdoc /> public void Build( IReadOnlyCollection <OwnedPropertyDescriptor> ownedProperties, IReadOnlyCollection <OwnedPropertyDescriptor> ownedBySource, MiddlewareBuilderContext context) { // Never apply if we are not in a HTTP-supported operation if (context.Descriptor.TryGetFeatureData <HttpOperationFeatureData>(out var _) == false) { return; } if (this._applies?.Invoke(context) == false) { return; } var operationVariable = context.FindVariable(context.Descriptor.OperationType); var httpContextVariable = context.FindVariable(typeof(HttpContext)); var sourceVariable = this._sourceCodeExpression(httpContextVariable); foreach (var prop in this._isCatchAll ? context.Descriptor.Properties : ownedBySource.Select(s => s.Property)) { if (prop.CanWrite == false) { continue; } // If this is a catch-all instance we DO NOT want to generate any code for a property // that is owned by a different source. if (this._isCatchAll && ownedProperties.Any(p => p.Property == prop)) { continue; } var partKey = this.GetPartKey(prop); var operationProperty = operationVariable.GetProperty(prop.Name); // When this property is not in ALL routes we use TryGetValue from the RouteData dictionary and pass // the var output from that to `GetConversionExpression` as part of ternary. If the route data // does not exist then we fallback to the value already on the operation var outVariableName = $"{this._variablePrefix}{prop.Name}"; var conversionExpression = GetConversionExpression(prop, outVariableName, this._supportsMultiValues, this._variablePrefix); var indexProperty = sourceVariable.VariableType.GetProperties().SingleOrDefault(p => p.GetIndexParameters().Length == 1); if (indexProperty == null) { throw new InvalidOperationException($"Source variable {sourceVariable} has no index property specified. Cannot use"); } var isStringValues = indexProperty.PropertyType == typeof(StringValues); var emptyCheckRhs = isStringValues ? $"{typeof(StringValues).FullNameInCode()}.Empty" : "null"; var source = $"{sourceVariable}[\"{partKey}\"]"; // We want to support the key naming scheme of key[] to indicate an array, therefore // we add a null-coalesce to partKey[] if (IsArrayLike(prop.PropertyType, out _)) { source = $"{source} == {emptyCheckRhs} ? {sourceVariable}[\"{partKey}[]\"] : {source}"; } var sourceVariableGetter = new VariableCreationFrame(typeof(object), outVariableName, source); // [Source] == null ? [conversion of valuePropertyName] : [operationProperty]; var tryConversionExpression = $"{sourceVariableGetter.CreatedVariable} != {emptyCheckRhs} ? " + $"{conversionExpression} : " + $"{operationProperty}"; context.AppendFrames( sourceVariableGetter, new VariableSetterFrame( operationProperty, tryConversionExpression), new BlankLineFrame()); } }
/// <inheritdoc /> public void Build(MiddlewareBuilderContext context) { var runNowCall = MethodCall.For <IBackgroundTaskScheduler>(s => s.RunNowAsync()); context.AppendFrames(runNowCall); }