/// <inheritdoc />
        public virtual object Create(ControllerContext controllerContext)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException(nameof(controllerContext));
            }

            if (controllerContext.ActionDescriptor == null)
            {
                throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull(
                                                nameof(ControllerContext.ActionDescriptor),
                                                nameof(ControllerContext)));
            }

            var controllerTypeInfo = controllerContext.ActionDescriptor.ControllerTypeInfo;

            if (controllerTypeInfo == null)
            {
                throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull(
                                                nameof(controllerContext.ActionDescriptor.ControllerTypeInfo),
                                                nameof(ControllerContext.ActionDescriptor)));
            }

            var serviceProvider = controllerContext.HttpContext.RequestServices;

            return(_typeActivatorCache.CreateInstance <object>(serviceProvider, controllerTypeInfo.AsType()));
        }
        public virtual object Create(ControllerContext controllerContext)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException(nameof(controllerContext));
            }
            if (controllerContext.ActionDescriptor == null)
            {
                throw new Exception();
            }
            var controllerTypeInfo = controllerContext.ActionDescriptor.ControllerTypeInfo;

            if (controllerTypeInfo is null)
            {
                throw new Exception();
            }
            var requestServices = controllerContext.HttpContext.RequestServices;
            var obj             = _typeActivatorCache.CreateInstance <object>(requestServices, controllerTypeInfo.AsType());

            foreach (var declaredProperty in controllerTypeInfo.DeclaredProperties)
            {
                declaredProperty.GetSetMethod(true).Invoke(obj, new object[1]
                {
                    ActivatorUtilities.GetServiceOrCreateInstance(requestServices, declaredProperty.PropertyType)
                });
            }
            return(obj);
        }
Esempio n. 3
0
        /// <summary>
        /// Initializes a new instance of <see cref="CompositeViewEngine"/>.
        /// </summary>
        /// <param name="optionsAccessor">The options accessor for <see cref="MvcOptions"/>.</param>
        /// <param name="typeActivatorCache">As <see cref="ITypeActivatorCache"/> instance that creates
        /// an instance of type <see cref="IViewEngine"/>.</param>
        /// <param name="serviceProvider">A <see cref="IServiceProvider"/> instance that retrieves services from the
        /// service collection.</param>
        public CompositeViewEngine(
            IOptions <MvcOptions> optionsAccessor,
            ITypeActivatorCache typeActivatorCache,
            IServiceProvider serviceProvider)
        {
            var viewEngines = new List <IViewEngine>();

            foreach (var descriptor in optionsAccessor.Options.ViewEngines)
            {
                IViewEngine viewEngine;
                if (descriptor.ViewEngine != null)
                {
                    viewEngine = descriptor.ViewEngine;
                }
                else
                {
                    viewEngine = typeActivatorCache.CreateInstance <IViewEngine>(
                        serviceProvider,
                        descriptor.ViewEngineType);
                }

                viewEngines.Add(viewEngine);
            }

            ViewEngines = viewEngines;
        }
Esempio n. 4
0
        /// <summary>
        /// Initializes a new instance of <see cref="CompositeViewEngine"/>.
        /// </summary>
        /// <param name="optionsAccessor">The options accessor for <see cref="MvcOptions"/>.</param>
        /// <param name="typeActivatorCache">As <see cref="ITypeActivatorCache"/> instance that creates
        /// an instance of type <see cref="IViewEngine"/>.</param>
        /// <param name="serviceProvider">A <see cref="IServiceProvider"/> instance that retrieves services from the
        /// service collection.</param>
        public CompositeViewEngine(
            IOptions<MvcOptions> optionsAccessor,
            ITypeActivatorCache typeActivatorCache,
            IServiceProvider serviceProvider)
        {
            var viewEngines = new List<IViewEngine>();
            foreach (var descriptor in optionsAccessor.Options.ViewEngines)
            {
                IViewEngine viewEngine;
                if (descriptor.ViewEngine != null)
                {
                    viewEngine = descriptor.ViewEngine;
                }
                else
                {
                    viewEngine = typeActivatorCache.CreateInstance<IViewEngine>(
                        serviceProvider, 
                        descriptor.ViewEngineType);
                }

                viewEngines.Add(viewEngine);
            }

            ViewEngines = viewEngines;
        }
Esempio n. 5
0
        public virtual object Create(CommandContext commandContext)
        {
            if (commandContext == null)
            {
                throw new ArgumentNullException(nameof(commandContext));
            }

            if (commandContext.CommandDescriptor == null)
            {
                throw new ArgumentException($"The '{nameof(CommandContext.CommandDescriptor)}' property of '" +
                                            $"{nameof(CommandContext)}' must not be null.");
            }

            var commandTypeInfo = commandContext.CommandDescriptor.CommandTypeInfo;

            if (commandTypeInfo == null)
            {
                throw new ArgumentException($"The '{nameof(commandContext.CommandDescriptor.CommandTypeInfo)}' property of '" +
                                            $"{nameof(CommandContext.CommandDescriptor)}' must not be null.");
            }

            var serviceProvider = commandContext.ServiceProvider;

            return(_typeActivatorCache.CreateInstance <object>(serviceProvider, commandTypeInfo.AsType()));
        }
        /// <inheritdoc />
        public virtual object Create(ControllerContext controllerContext)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException(nameof(controllerContext));
            }

            if (controllerContext.ActionDescriptor == null)
            {
                throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull(
                                                nameof(ControllerContext.ActionDescriptor),
                                                nameof(ControllerContext)));
            }

            var controllerTypeInfo = controllerContext.ActionDescriptor.ControllerTypeInfo;

            if (controllerTypeInfo.IsValueType ||
                controllerTypeInfo.IsInterface ||
                controllerTypeInfo.IsAbstract ||
                (controllerTypeInfo.IsGenericType && controllerTypeInfo.IsGenericTypeDefinition))
            {
                var message = Resources.FormatValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated(
                    controllerTypeInfo.FullName,
                    GetType().FullName);

                throw new InvalidOperationException(message);
            }

            var serviceProvider = controllerContext.HttpContext.RequestServices;

            return(_typeActivatorCache.CreateInstance <object>(serviceProvider, controllerTypeInfo.AsType()));
        }
        /// <inheritdoc />
        public virtual object Create(ViewComponentContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var componentType = context.ViewComponentDescriptor.TypeInfo;

            if (componentType.IsValueType ||
                componentType.IsInterface ||
                componentType.IsAbstract ||
                (componentType.IsGenericType && componentType.IsGenericTypeDefinition))
            {
                var message = Resources.FormatValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated(
                    componentType.FullName,
                    GetType().FullName);

                throw new InvalidOperationException(message);
            }

            var viewComponent = _typeActivatorCache.CreateInstance <object>(
                context.ViewContext.HttpContext.RequestServices,
                context.ViewComponentDescriptor.TypeInfo.AsType());

            return(viewComponent);
        }
        private object CreateComponent([NotNull] ViewComponentContext context)
        {
            var component = _typeActivatorCache.CreateInstance <object>(
                _serviceProvider,
                context.ViewComponentDescriptor.Type);

            _viewComponentActivator.Activate(component, context.ViewContext);
            return(component);
        }
Esempio n. 9
0
        private object CreateComponent([NotNull] ViewComponentContext context)
        {
            var services  = context.ViewContext.HttpContext.RequestServices;
            var component = _typeActivatorCache.CreateInstance <object>(
                services,
                context.ViewComponentDescriptor.Type);

            _viewComponentActivator.Activate(component, context);
            return(component);
        }
Esempio n. 10
0
        /// <summary>
        /// Creates a widget instance.
        /// </summary>
        /// <param name="context">The widget context.</param>
        /// <returns>The wiget instance.</returns>
        private object CreateWidget(WidgetContext context)
        {
            var services = context.ViewContext.HttpContext.RequestServices;
            var widget   = _typeActivatorCache.CreateInstance <object>(
                services,
                context.WidgetDescriptor.Type);

            _widgetActivator.Activate(widget, context);

            return(widget);
        }
Esempio n. 11
0
        public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
        {
            var scope = (DependencyScope)request.GetDependencyScope();

            //var disposable = controller as IDisposable;
            //if (disposable != null)
            //{
            //    request.RegisterForDispose(disposable);
            //}

            return((IHttpController)_typeActivatorCache.CreateInstance <object>(scope.GetServiceProvider(), controllerType));
        }
Esempio n. 12
0
        /// <inheritdoc />
        public TTagHelper Create <TTagHelper>(ViewContext context)
            where TTagHelper : ITagHelper
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            return(_typeActivatorCache.CreateInstance <TTagHelper>(
                       context.HttpContext.RequestServices,
                       typeof(TTagHelper)));
        }
Esempio n. 13
0
        public object Create(ControllerContext controllerContext)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException(nameof(controllerContext));
            }

            if (controllerContext.ActionDescriptor == null)
            {
                throw new ArgumentException(nameof(ControllerContext.ActionDescriptor));
            }

            var controllerTypeInfo = controllerContext.ActionDescriptor.ControllerTypeInfo;

            if (controllerTypeInfo == null)
            {
                throw new ArgumentException(nameof(controllerContext.ActionDescriptor.ControllerTypeInfo));
            }

            var serviceProvider = controllerContext.HttpContext.RequestServices;
            var instance        = _typeActivatorCache.CreateInstance <object>(serviceProvider, controllerTypeInfo.AsType());

            if (instance != null)
            {
                if (!_publicPropertyCache.ContainsKey(controllerTypeInfo.FullName))
                {
                    var ps = controllerTypeInfo.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic)
                             .Where(c => c.GetCustomAttribute <InjectionAttribute>() != null);
                    _publicPropertyCache[controllerTypeInfo.FullName] = ps;
                }

                var injectionProperties = _publicPropertyCache[controllerTypeInfo.FullName];
                foreach (var item in injectionProperties)
                {
                    var service = serviceProvider.GetService(item.PropertyType);
                    if (service == null)
                    {
                        throw new InvalidOperationException($"Unable to resolve service for type '{item.PropertyType.FullName}' while attempting to activate '{controllerTypeInfo.FullName}'");
                    }
                    item.SetValue(instance, service);
                }
                foreach (FieldInfo field in controllerTypeInfo.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    var autowiredAttr = field.GetCustomAttribute <InjectionAttribute>();
                    if (autowiredAttr != null)
                    {
                        field.SetValue(instance, serviceProvider.GetService(field.FieldType));
                    }
                }
            }
            return(instance);
        }
Esempio n. 14
0
        private object CreateComponent(ViewComponentContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var services  = context.ViewContext.HttpContext.RequestServices;
            var component = _typeActivatorCache.CreateInstance <object>(
                services,
                context.ViewComponentDescriptor.Type);

            _viewComponentActivator.Activate(component, context);
            return(component);
        }
Esempio n. 15
0
        /// <inheritdoc />
        public virtual object Create(ActionContext actionContext, Type controllerType)
        {
            if (actionContext == null)
            {
                throw new ArgumentNullException(nameof(actionContext));
            }

            if (controllerType == null)
            {
                throw new ArgumentNullException(nameof(controllerType));
            }

            var serviceProvider = actionContext.HttpContext.RequestServices;

            return(_typeActivatorCache.CreateInstance <object>(serviceProvider, controllerType));
        }
        public object Create(WidgetViewContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var componentType = context.ComponentDescriptor.TypeInfo;

            if (componentType == null)
            {
                throw new ArgumentNullException(nameof(context.ComponentDescriptor.TypeInfo));
            }

            var viewComponent = _typeActivatorCache.CreateInstance <object>(
                context.ViewContext.HttpContext.RequestServices,
                context.ComponentDescriptor.TypeInfo.AsType());

            return(viewComponent);
        }
Esempio n. 17
0
    /// <inheritdoc />
    public object Create(ViewComponentContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        var componentType = context.ViewComponentDescriptor.TypeInfo;

        if (componentType == null)
        {
            throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull(
                                            nameof(context.ViewComponentDescriptor.TypeInfo),
                                            nameof(context.ViewComponentDescriptor)));
        }

        var viewComponent = _typeActivatorCache.CreateInstance <object>(
            context.ViewContext.HttpContext.RequestServices,
            context.ViewComponentDescriptor.TypeInfo.AsType());

        return(viewComponent);
    }
        public override object Create(ControllerContext controllerContext)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException(nameof(controllerContext));
            }

            if (controllerContext.ActionDescriptor == null)
            {
                throw new ArgumentException("");
            }

            var controllerTypeInfo = controllerContext.ActionDescriptor.ControllerTypeInfo;

            if (controllerTypeInfo == null)
            {
                throw new ArgumentException("");
            }

            var serviceProvider = controllerContext.HttpContext.RequestServices;

            return(_typeActivatorCache.CreateInstance <object>(serviceProvider, controllerTypeInfo.AsType()));
        }
Esempio n. 19
0
        public override object Create(ControllerContext controllerContext)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException(nameof(controllerContext));
            }

            if (controllerContext.ActionDescriptor == null)
            {
                throw new ArgumentException(nameof(ControllerContext.ActionDescriptor));
            }

            var controllerTypeInfo = controllerContext.ActionDescriptor.ControllerTypeInfo;

            if (controllerTypeInfo == null)
            {
                throw new ArgumentException(nameof(controllerContext.ActionDescriptor.ControllerTypeInfo));
            }

            var serviceProvider = controllerContext.HttpContext.RequestServices;
            var instance        = _typeActivatorCache.CreateInstance <object>(serviceProvider, controllerTypeInfo.AsType());

            if (instance != null)
            {
                var serviceType = controllerTypeInfo.AsType();
                if (autowiredActions.TryGetValue(serviceType, out Action <object, IServiceProvider> act))
                {
                    act(instance, serviceProvider);
                }
                else
                {
                    //参数
                    var objParam = Expression.Parameter(typeof(object), "obj");
                    var spParam  = Expression.Parameter(typeof(IServiceProvider), "sp");

                    var obj                   = Expression.Convert(objParam, serviceType);
                    var getService            = typeof(IServiceProvider).GetMethod("GetService");
                    List <Expression> setList = new List <Expression>();

                    //字段赋值
                    foreach (FieldInfo field in serviceType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                    {
                        var autowiredAttr = field.GetCustomAttribute <AutowiredAttribute>();
                        if (autowiredAttr != null)
                        {
                            var fieldExp      = Expression.Field(obj, field);
                            var createService = Expression.Call(spParam, getService, Expression.Constant(field.FieldType));
                            //var createService=Expression.Call(getService, spParam, Expression.Constant(field.FieldType));
                            var setExp = Expression.Assign(fieldExp, Expression.Convert(createService, field.FieldType));
                            setList.Add(setExp);
                        }
                    }

                    //属性赋值
                    foreach (PropertyInfo property in serviceType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                    {
                        var autowiredAttr = property.GetCustomAttribute <AutowiredAttribute>();
                        if (autowiredAttr != null)
                        {
                            var propExp       = Expression.Property(obj, property);
                            var createService = Expression.Call(spParam, getService, Expression.Constant(property.PropertyType));
                            var setExp        = Expression.Assign(propExp, Expression.Convert(createService, property.PropertyType));
                            setList.Add(setExp);
                        }
                    }

                    var bodyExp   = Expression.Block(setList);
                    var setAction = Expression.Lambda <Action <object, IServiceProvider> >(bodyExp, objParam, spParam).Compile();
                    autowiredActions[serviceType] = setAction;
                    setAction(instance, serviceProvider);
                }

                #region 反射
                //if (!_publicPropertyCache.ContainsKey(controllerTypeInfo.FullName))
                //{
                //    var ps = controllerTypeInfo.GetProperties(BindingFlags.Instance).AsEnumerable();
                //    ps = ps.Where(c => c.GetCustomAttribute<AutowiredAttribute>() != null);
                //    _publicPropertyCache[controllerTypeInfo.FullName] = ps;
                //}

                //var requireServices = _publicPropertyCache[controllerTypeInfo.FullName];
                //foreach (var item in requireServices)
                //{
                //    var service = serviceProvider.GetService(item.PropertyType);
                //    if (service == null)
                //    {
                //        throw new InvalidOperationException($"Unable to resolve service for type '{item.PropertyType.FullName}' while attempting to activate '{controllerTypeInfo.FullName}'");
                //    }
                //    item.SetValue(instance, service);
                //}
                #endregion
            }
            return(instance);
        }
        internal async Task OnIncomingApplicationMessage(AspNetMqttServerOptionsBuilder options, MqttApplicationMessageInterceptorContext context)
        {
            // Don't process messages sent from the server itself. This avoids footguns like a server failing to publish
            // a message because a route isn't found on a controller.
            if (context.ClientId == null)
            {
                return;
            }

            var routeContext = new MqttRouteContext(context.ApplicationMessage.Topic);

            routeTable.Route(routeContext);

            if (routeContext.Handler == null)
            {
                // Route not found
                logger.LogDebug($"Rejecting message publish because '{context.ApplicationMessage.Topic}' did not match any known routes.");

                context.AcceptPublish = false;
            }
            else
            {
                using (var scope = options.ServiceProvider.CreateScope())
                {
                    Type?declaringType = routeContext.Handler.DeclaringType;

                    if (declaringType == null)
                    {
                        throw new InvalidOperationException($"{routeContext.Handler} must have a declaring type.");
                    }

                    var classInstance = typeActivator.CreateInstance <object>(scope.ServiceProvider, declaringType);

                    // Potential perf improvement is to cache this reflection work in the future.
                    var activateProperties = declaringType.GetRuntimeProperties()
                                             .Where((property) =>
                    {
                        return
                        (property.IsDefined(typeof(MqttControllerContextAttribute)) &&
                         property.GetIndexParameters().Length == 0 &&
                         property.SetMethod != null &&
                         !property.SetMethod.IsStatic);
                    })
                                             .ToArray();

                    if (activateProperties.Length == 0)
                    {
                        logger.LogDebug($"MqttController '{declaringType.FullName}' does not have a property that can accept a controller context.  You may want to add a [{nameof(MqttControllerContextAttribute)}] to a pubilc property.");
                    }

                    var controllerContext = new MqttControllerContext()
                    {
                        MqttContext = context,
                        MqttServer  = scope.ServiceProvider.GetRequiredService <IMqttServer>()
                    };

                    for (int i = 0; i < activateProperties.Length; i++)
                    {
                        PropertyInfo property = activateProperties[i];
                        property.SetValue(classInstance, controllerContext);
                    }

                    ParameterInfo[] parameters = routeContext.Handler.GetParameters();

                    context.AcceptPublish = true;

                    if (parameters.Length == 0)
                    {
                        await HandlerInvoker(routeContext.Handler, classInstance, null).ConfigureAwait(false);
                    }
                    else
                    {
                        object?[] paramArray;

                        try
                        {
                            paramArray = parameters.Select(p => MatchParameterOrThrow(p, routeContext.Parameters)).ToArray();

                            await HandlerInvoker(routeContext.Handler, classInstance, paramArray).ConfigureAwait(false);
                        }
                        catch (ArgumentException ex)
                        {
                            logger.LogError(ex, $"Unable to match route parameters to all arguments. See inner exception for details.");

                            context.AcceptPublish = false;
                        }
                        catch (TargetInvocationException ex)
                        {
                            logger.LogError(ex.InnerException, $"Unhandled MQTT action exception. See inner exception for details.");

                            // This is an unandled exception from the invoked action
                            context.AcceptPublish = false;
                        }
                        catch (Exception ex)
                        {
                            logger.LogError(ex, "Unable to invoke Mqtt Action.  See inner exception for details.");

                            context.AcceptPublish = false;
                        }
                    }
                }
            }
        }
Esempio n. 21
0
        public async Task <IActionResult> InvokeAction(HttpContext httpContext, ModuleAction moduleAction, ActionContext actionContext)
        {
            IActionResult result = null;

            var targetController = _allControllers.FirstOrDefault(c => c.Namespace == moduleAction.ControllerNamespace && c.Name == moduleAction.ControllerName + ControllerTypeNameSuffix);

            if (targetController == null)
            {
                throw new Exception("Module Controller not found");
            }

            var targetAction = targetController.GetMethods().FirstOrDefault(m => m.Name == moduleAction.ActionName);

            if (targetAction == null)
            {
                throw new Exception("Module Action not found");
            }

            var executor = _cache.GetExecutor(targetAction, targetController);

            var actionArguments = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase);

            var arguments = PrepareArguments(actionArguments, executor);

            var returnType = executor.MethodReturnType;

            var controllerContext = new ControllerContext(actionContext);
            //var controller1 = _controllerFactory.CreateController(controllerContext);

            var serviceProvider = httpContext.RequestServices;
            var controller      = _typeActivatorCache.CreateInstance <object>(serviceProvider, targetController.AsType()); //Returns

            foreach (var propertyActivator in _propertyActivators)
            {
                propertyActivator.Activate(controllerContext, controller);
            }

            //((Deviser.Core.Library.Controllers.DeviserController)controller).TempData = new TempDataDictionary()

            if (returnType == typeof(void))
            {
                executor.Execute(controller, arguments);
                result = new EmptyResult();
            }
            else if (returnType == typeof(Task))
            {
                await(Task) executor.Execute(controller, arguments);
                result = new EmptyResult();
            }
            else if (executor.TaskGenericType == typeof(IActionResult))
            {
                result = await(Task <IActionResult>) executor.Execute(controller, arguments);
                if (result == null)
                {
                    throw new InvalidOperationException(
                              Resources.FormatActionResult_ActionReturnValueCannotBeNull(typeof(IActionResult)));
                }
            }
            else if (executor.IsTypeAssignableFromIActionResult)
            {
                if (executor.IsMethodAsync)
                {
                    result = (IActionResult)await executor.ExecuteAsync(controller, arguments);
                }
                else
                {
                    result = (IActionResult)executor.Execute(controller, arguments);
                }

                if (result == null)
                {
                    throw new InvalidOperationException(
                              Resources.FormatActionResult_ActionReturnValueCannotBeNull(executor.TaskGenericType ?? returnType));
                }
            }
            else if (!executor.IsMethodAsync)
            {
                var resultAsObject = executor.Execute(controller, arguments);
                result = new ObjectResult(resultAsObject)
                {
                    DeclaredType = returnType,
                };
            }
            else if (executor.TaskGenericType != null)
            {
                var resultAsObject = await executor.ExecuteAsync(controller, arguments);

                result = new ObjectResult(resultAsObject)
                {
                    DeclaredType = executor.TaskGenericType,
                };
            }
            else
            {
                // This will be the case for types which have derived from Task and Task<T> or non Task types.
                throw new InvalidOperationException(Resources.FormatActionExecutor_UnexpectedTaskInstance(
                                                        executor.MethodInfo.Name,
                                                        executor.MethodInfo.DeclaringType));
            }

            ((IDisposable)controller).RegisterForDispose(httpContext);

            return(result);
        }
        /// <inheritdoc />
        public virtual object Create([NotNull] ActionContext actionContext, [NotNull] Type controllerType)
        {
            var serviceProvider = actionContext.HttpContext.RequestServices;

            return(_typeActivatorCache.CreateInstance <object>(serviceProvider, controllerType));
        }