Ejemplo n.º 1
0
        public DependencyContainer Register(string name, Type type, Func <object> builder)
        {
            var cacheKey = new NameAndType(name, type);

            if (!_registrations.TryGetValue(cacheKey, out var list))
            {
                _registrations.TryAdd(cacheKey, list = new List <Func <object> >());
            }

            list.Add(builder);

            var enumerableCacheKey = new NameAndType($"{Constants.EnumerableSlot}{name}", typeof(IEnumerable <>).MakeGenericType(type));

            if (_registrations.TryGetValue(enumerableCacheKey, out var enumerableList))
            {
                return(this);
            }

            if (_registrations.TryAdd(enumerableCacheKey, enumerableList = new List <Func <object> >()))
            {
                enumerableList.Add(() =>
                {
                    var collection = (IList)Instancing.CreateInstance(typeof(List <>).MakeGenericType(type));
                    foreach (var itemBuilder in list)
                    {
                        collection.Add(itemBuilder());
                    }
                    return(collection);
                });
            }

            return(this);
        }
Ejemplo n.º 2
0
 private TPrototype TryGetImplementation <TInterface, TPrototype>()
     where TPrototype : class, TInterface
 {
     return(ServiceProvider?.GetService(typeof(TPrototype)) as TPrototype ??
            Instancing.CreateInstance <TPrototype>() ??
            Dummy <TPrototype>());
 }
Ejemplo n.º 3
0
        public IActionResult Patch([FromQuery] string type, [FromBody] JsonPatchDocument patch,
                                   [FromRoute] string section = null)
        {
            if (string.IsNullOrWhiteSpace(section))
            {
                return(this.NotAcceptableError(ErrorEvents.UnsafeRequest,
                                               "You must specify a known configuration sub-section, to avoid exposing sensitive root-level data."));
            }

            var prototype = ResolvePrototypeName(type);

            if (prototype == null)
            {
                return(this.NotAcceptableError(ErrorEvents.InvalidParameter,
                                               $"No configuration type found with name '{type}'."));
            }

            var config = _root.GetSection(section.Replace("/", ":"));

            if (config == null)
            {
                return(this.NotFoundError(ErrorEvents.InvalidParameter,
                                          $"Configuration sub-section path '{section}' not found."));
            }

            var model = Instancing.CreateInstance(prototype);

            config.FastBind(model, _customBinders);
            patch.ApplyTo(model);

            return(Put(type, model, section));
        }
Ejemplo n.º 4
0
        public static TBuilder AddActiveRoute <TBuilder, TController, TFeature, TFeatureOptions>(
            this IMvcCoreBuilder mvcBuilder)
            where TBuilder : IFeatureBuilder
            where TFeature : class, IDynamicFeature
            where TFeatureOptions : class
        {
            AddActiveRouteImpl <TController, TFeature, TFeatureOptions>(mvcBuilder);

            return(Instancing.CreateInstance <TBuilder>(mvcBuilder.Services));
        }
Ejemplo n.º 5
0
        public override ShapedData <T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType != JsonTokenType.StartObject)
            {
                throw new JsonException();
            }

            T data;

            if (typeof(T).ImplementsGeneric(typeof(Many <>)))
            {
                // FIXME: Instancing can't handle nested generic types, so we have to use manual reflection here
                //        until it is resolved.
                var underlyingType = typeof(T).GetGenericArguments()[0];
                var enumerableType = typeof(List <>).MakeGenericType(underlyingType);
                var enumerable     = Activator.CreateInstance(enumerableType);
                data = (T)(Activator.CreateInstance(typeof(T), enumerable) ?? throw new NullReferenceException());
            }
            else
            {
                data = Instancing.CreateInstance <T>();
            }

            while (reader.Read())
            {
                if (reader.TokenType == JsonTokenType.EndObject)
                {
                    return(new ShapedData <T>(data)); // success: end of object
                }
                if (reader.TokenType != JsonTokenType.PropertyName)
                {
                    throw new JsonException(); // fail: did not pass through previous property value
                }
                var key = reader.GetString();

                if (string.IsNullOrWhiteSpace(key) || !_members.TryGetValue(key, out var member) || !member.CanWrite)
                {
                    continue;
                }

                var value = JsonSerializer.Deserialize(ref reader, member.Type, options);

                if (!_writer.TrySetValue(data, key, value !))
                {
                    throw new JsonException();
                }
            }

            // fail: passed through JsonTokenType.EndObject
            throw new JsonException();
        }
Ejemplo n.º 6
0
        private object BindTemplateInstance(Type type, IConfiguration config)
        {
            lock (Sync)
            {
                var template = Instancing.CreateInstance(type);
                if (!_empties.TryGetValue(type, out _))
                {
                    _empties.Add(type, ValueHash.ComputeHash(template));
                }

                config.FastBind(template, _customBinders);
                return(ValueHash.ComputeHash(template) == _empties[type] ? null : template);
            }
        }
Ejemplo n.º 7
0
        // ReSharper disable once SuggestBaseTypeForParameter
        private static object GetTestContainerInstance(Type type, TestFixture fixture, IMessageLogger logger)
        {
            logger?.SendMessage(TestMessageLevel.Informational, $"Creating instance for type {type.FullName}");

            object instance = null;

            try
            {
                if (type.GetConstructor(new[] { typeof(TestFixture) }) != null)
                {
                    logger?.SendMessage(TestMessageLevel.Informational, $"{type.Name}(TestFixture fixture) {{ ... }}");
                    instance = Instancing.CreateInstance(type, fixture);
                }
                else if (type.GetConstructor(new[] { typeof(IServiceCollection) }) != null)
                {
                    logger?.SendMessage(TestMessageLevel.Informational,
                                        $"{type.Name}(IServiceCollection services) {{ ... }}");
                    instance = Instancing.CreateInstance(type, fixture);
                }
                else if (type.GetConstructor(new[] { typeof(IServiceProvider) }) != null)
                {
                    logger?.SendMessage(TestMessageLevel.Informational,
                                        $"{type.Name}(IServiceProvider serviceProvider) {{ ... }}");
                    instance = Instancing.CreateInstance(type, fixture);
                }
                else if (type.GetConstructor(Type.EmptyTypes) != null)
                {
                    logger?.SendMessage(TestMessageLevel.Informational, $"{type.Name}() {{ ... }}");
                    instance = Instancing.CreateInstance(type);
                }
            }
            catch (Exception e)
            {
                logger?.SendMessage(TestMessageLevel.Error, e.ToString());
                instance = null;
            }

            if (instance != null)
            {
                return(instance);
            }

            logger?.SendMessage(TestMessageLevel.Error,
                                "Could not find a suitable constructor for the test containing class");
            return(null);
        }
 protected GivenACollectionStore(string endpoint, ITestOutputHelper output,
                                 WebApplicationFactory <TStartup> factory)
 {
     _endpoint = endpoint;
     _factory  = factory.WithTestLogging(output)
                 .WithoutLocalizationStartupService()
                 .WithWebHostBuilder(builder =>
     {
         builder.ConfigureTestServices(services =>
         {
             services.RemoveAll <TService>();
             services.AddSingleton(r =>
             {
                 var service = Instancing.CreateInstance <TService>(services.BuildServiceProvider());
                 Populate(service);
                 return(service);
             });
         });
     });
 }
Ejemplo n.º 9
0
        public void Invoke(string handler)
        {
            if (!_handlers.TryGetValue(handler, out var accessor))
            {
                var tokens = handler.Split('.');
                if (tokens.Length > 1)
                {
                    var typeString   = tokens[0];
                    var methodString = tokens[1];

                    var resolver = UiServices.GetRequiredService <ITypeResolver>();
                    var type     = resolver.FindFirstByName(typeString);
                    var method   = type.GetMethod(methodString);

                    _instances[handler] = Instancing.CreateInstance(type, UiServices);
                    _handlers[handler]  = accessor = CallAccessor.Create(method);
                }
            }

            accessor?.Call(_instances[handler], UiServices);
        }
Ejemplo n.º 10
0
        public static object ToAnonymousObject(IDictionary <string, object> hash)
        {
            var anonymousType = TypeFactory.BuildAnonymousType(hash);
            var instance      = Instancing.CreateInstance(anonymousType);
            var accessor      = WriteAccessor.Create(anonymousType, AccessorMemberTypes.Properties,
                                                     AccessorMemberScope.Public, out var members);

            foreach (var member in members)
            {
                if (!member.CanWrite)
                {
                    continue; // should be accessible by design
                }
                if (!hash.TryGetValue(member.Name, out var value))
                {
                    continue; // should be mapped one-to-one
                }
                accessor.TrySetValue(instance, member.Name, value);
            }

            return(instance);
        }
Ejemplo n.º 11
0
        public bool TryResolve(string name, Type type, out object instance)
        {
            var cacheKey = new NameAndType(name, type);

            if (typeof(IEnumerable).IsAssignableFrom(type))
            {
                var enumerableCacheKey = new NameAndType($"{Constants.EnumerableSlot}{name}", typeof(IEnumerable <>).MakeGenericType(type.GetGenericArguments()));
                if (_registrations.TryGetValue(enumerableCacheKey, out var enumerableList))
                {
                    foreach (var entry in enumerableList)
                    {
                        instance = entry();

                        if (!_registrations.ContainsKey(cacheKey))
                        {
                            return(true); // nothing to merge
                        }
                        var merged = (IList)Instancing.CreateInstance(typeof(List <>).MakeGenericType(type.GetGenericArguments()));
                        foreach (var x in (IList)instance)
                        {
                            merged.Add(x);
                        }

                        if (_registrations.TryGetValue(cacheKey, out var singleList))
                        {
                            foreach (var y in singleList)
                            {
                                foreach (var x in (IList)y())
                                {
                                    merged.Add(x);
                                }

                                break;
                            }
                        }

                        instance = merged;
                        return(true);
                    }
                }
            }

            if (_registrations.TryGetValue(cacheKey, out var list))
            {
                foreach (var entry in list)
                {
                    instance = entry();
                    return(true);
                }
            }

            if (!type.IsAbstract)
            {
                instance = Instancing.CreateInstance(type, this);
                if (instance != null)
                {
                    return(true);
                }
            }

            instance = _fallback?.GetService(type);
            if (instance != null)
            {
                return(true);
            }

            instance = default;
            return(false);
        }
        private static void BindNonScalar(this IConfiguration configuration, ref object instance, BinderOptions options,
                                          IEnumerable <ICustomConfigurationBinder> customBinders)
        {
            if (instance == null)
            {
                return;
            }

            var scope = AccessorMemberScope.Public;

            if (options.BindNonPublicProperties)
            {
                scope |= AccessorMemberScope.Private;
            }

            var type  = instance.GetType();
            var read  = ReadAccessor.Create(type, AccessorMemberTypes.Properties, scope, out var members);
            var write = WriteAccessor.Create(type, AccessorMemberTypes.Properties, scope);

            if (IsTypeDiscriminated(type, out _))
            {
                // Set base properties so the converter has the right values to work with
                SetMembers(configuration, instance, options, members, read, write, customBinders);

                // Give a custom converter a chance to change what is bound
                var converter = TypeDescriptor.GetConverter(type);
                if (converter.CanConvertFrom(type))
                {
                    instance = converter.ConvertFrom(instance);
                    if (instance != null)
                    {
                        type  = instance.GetType();
                        read  = ReadAccessor.Create(type, AccessorMemberTypes.Properties, scope, out members);
                        write = WriteAccessor.Create(type, AccessorMemberTypes.Properties, scope);
                    }
                }
                else
                {
                    foreach (var binder in customBinders ?? Enumerable.Empty <ICustomConfigurationBinder>())
                    {
                        if (!binder.CanConvertFrom(type))
                        {
                            continue;
                        }

                        var subType = binder.GetTypeFor(instance);
                        if (subType == null)
                        {
                            continue;
                        }

                        type     = subType;
                        instance = Instancing.CreateInstance(type);
                        read     = ReadAccessor.Create(type, AccessorMemberTypes.Properties, scope, out members);
                        write    = WriteAccessor.Create(type, AccessorMemberTypes.Properties, scope);
                        goto setMembers;
                    }
                }
            }

setMembers:
            SetMembers(configuration, instance, options, members, read, write, customBinders);
        }
Ejemplo n.º 13
0
        private static void AddActiveRouteImpl <TController, TFeature, TFeatureOptions>(IMvcCoreBuilder mvcBuilder)
            where TFeature : class, IDynamicFeature
            where TFeatureOptions : class
        {
            // Add [DynamicController(typeof(TComponentOptions))] if not present
            if (!typeof(TController).HasAttribute <DynamicControllerAttribute>())
            {
                var attribute = new DynamicControllerAttribute(typeof(TFeatureOptions));
                TypeDescriptor.AddAttributes(typeof(TController), attribute);
                var attributes = TypeDescriptor.GetAttributes(typeof(TController));
                if (!attributes.Contains(attribute))
                {
                    throw new InvalidOperationException("Could not add attribute dynamically on this runtime.");
                }
            }

            // See: https://github.com/aspnet/Mvc/issues/5992
            mvcBuilder.AddApplicationPart(typeof(TController).Assembly);
            mvcBuilder.ConfigureApplicationPartManager(x =>
            {
                x.ApplicationParts.Add(new DynamicControllerApplicationPart(new[] { typeof(TController).GetTypeInfo() }));
            });

            var componentDescriptor = ServiceDescriptor.Singleton(r =>
            {
                var component = Instancing.CreateInstance <TFeature>();
                component.GetRouteTemplate = () =>
                {
                    var o = r.GetRequiredService <IOptionsMonitor <TFeatureOptions> >();
                    return(o.CurrentValue is IFeatureNamespace ns ? ns.RootPath ?? string.Empty : string.Empty);
                };
                return(component);
            });

            mvcBuilder.Services.Replace(componentDescriptor);
            mvcBuilder.Services.AddTransient <IDynamicFeature>(r =>
            {
                // cached singleton
                var component = r.GetService <TFeature>();

                // each resolution, we could be discovering a different controller that needs hydration into its type
                for (var i = 0; i < component.ControllerTypes.Count; i++)
                {
                    var controllerType = component.ControllerTypes[i];
                    if (controllerType.IsGenericType && controllerType.Name == typeof(TController).Name)
                    {
                        component.ControllerTypes[i] = typeof(TController);
                    }
                }

                return(component);
            });

            mvcBuilder.AddAuthorization(x =>
            {
                if (x.GetPolicy(Constants.Security.Policies.NoPolicy) == null)
                {
                    x.AddPolicy(Constants.Security.Policies.NoPolicy, b => { b.RequireAssertion(context => true); });
                }
            });
        }
Ejemplo n.º 14
0
        public static IHostBuilder ConfigureApiServer <TStartup>(this IHostBuilder builder, Func <IConfiguration, IConfiguration>?configSelector = default) where TStartup : class
        {
            TStartup?startup = default;

            builder.ConfigureLogging((context, loggingBuilder) =>
            {
                loggingBuilder.AddLightingDb("logging");
            });

            builder.ConfigureAppConfiguration((context, configBuilder) => { });

            builder.ConfigureWebHostDefaults(configure =>
            {
                configure.UseKestrel(o =>
                {
                    o.AddServerHeader = false; // we add our own header via configuration
                });

                configure.UseStartup <TStartup>(); // only called for method validation
                configure.UseStaticWebAssets();

                configure.ConfigureServices((context, services) =>
                {
                    var config = configSelector != default
                        ? configSelector(context.Configuration)
                        : context.Configuration.GetSection(Constants.DefaultConfigSection);

                    var startupAssembly = typeof(TStartup).Assembly;

                    // Resource assemblies:
                    //
                    foreach (var dependent in startupAssembly.GetReferencedAssemblies())
                    {
                        Assembly.Load(dependent);
                    }
                    var resourceAssemblies = new HashSet <Assembly>
                    {
                        // BetterAPI
                        typeof(ApiOptions).Assembly,

                        // BetterAPI.Primitives
                        typeof(User).Assembly,

                        // User application
                        startupAssembly
                    };
                    foreach (var type in AppDomain.CurrentDomain.GetAssemblies()
                             .Where(a => !a.IsDynamic)
                             .SelectMany(x => x.GetTypes()))
                    {
                        if (type.IsInterface || !typeof(IResource).IsAssignableFrom(type))
                        {
                            continue;
                        }
                        if (resourceAssemblies.Contains(type.Assembly))
                        {
                            continue;
                        }

                        resourceAssemblies.Add(type.Assembly);
                    }

                    services.AddApiServer(config, context.HostingEnvironment, resourceAssemblies);

                    //
                    // The default ApplicationPartManager relies on the entryAssemblyName, which is this library.
                    // So we need to register the calling application's own controllers as well, here.
                    var mvcBuilder = services.AddControllers();
                    foreach (var assembly in resourceAssemblies)
                    {
                        mvcBuilder.AddApplicationPart(assembly);
                    }

                    //
                    // Calling `configure.UseStartup<TStartup>()` will replace our defaults, so call manually:
                    var serviceProvider = services.BuildServiceProvider();
                    startup ??= Instancing.CreateInstance <TStartup>(serviceProvider);
                    var accessor = CallAccessor.Create(typeof(TStartup).GetMethod(nameof(IStartup.ConfigureServices)) ??
                                                       throw new InvalidOperationException());
                    accessor.Call(startup, new object[] { services });
                });

                configure.Configure((context, app) =>
                {
                    app.UseApiServer(context.HostingEnvironment);

                    //
                    // Calling `configure.UseStartup<TStartup>()` will replace our defaults, so call manually:
                    startup ??= Instancing.CreateInstance <TStartup>(app.ApplicationServices);
                    var accessor = CallAccessor.Create(typeof(TStartup).GetMethod(nameof(IStartup.Configure)) ??
                                                       throw new InvalidOperationException());
                    accessor.Call(startup, new AppBuilderServiceProvider(app, app.ApplicationServices));
                });
            });

            return(builder);
        }