예제 #1
0
 /// <summary>
 /// Registers a new ServiceConfiguration.
 /// </summary>
 /// <typeparam name="TKeyType">The primary lookup key type for the current service configuration.</typeparam>
 /// <param name="keyName">The primary lookup key name for the current service configuration.</param>
 /// <param name="lifetime">The default lifetime for the described service.</param>
 /// <param name="typeFactory">The <see cref="ITypeFactory.Type"/> to be used when building a new instance of this service.</param>
 /// <param name="baseCacheKey">The minimum cache key. All ancestors between <paramref name="baseCacheKey"/> and <paramref name="key"/> will be used as <see cref="ServiceConfigurationContext.CacheKeys"/>.</param>
 /// <param name="priority">The priority value for this specific descriptor. All services will be sorted by priority when their the service provider is created.</param>
 public void RegisterServiceConfiguration <TKeyType>(
     String keyName,
     ServiceLifetime lifetime,
     Type typeFactory,
     ServiceConfigurationKey baseCacheKey,
     Int32 priority = 0)
 => this.Add(new ServiceConfigurationContext(ServiceConfigurationKey.From <TKeyType>(keyName), lifetime, typeFactory, baseCacheKey, priority));
예제 #2
0
 /// <summary>
 /// Registers a new ServiceConfiguration.
 /// </summary>
 /// <param name="key">The primary lookup key for the current service configuration.</param>
 /// <param name="lifetime">The default lifetime for the described service.</param>
 /// <param name="typeFactory">The <see cref="ITypeFactory.Type"/> to be used when building a new instance of this service.</param>
 /// <param name="baseCacheKey">The minimum cache key. All ancestors between <paramref name="baseCacheKey"/> and <paramref name="key"/> will be used as <see cref="ServiceConfigurationContext.CacheKeys"/>.</param>
 /// <param name="priority">The priority value for this specific descriptor. All services will be sorted by priority when their the service provider is created.</param>
 public void RegisterServiceConfiguration(
     ServiceConfigurationKey key,
     ServiceLifetime lifetime,
     Type typeFactory,
     ServiceConfigurationKey baseCacheKey,
     Int32 priority = 0)
 => this.Add(new ServiceConfigurationContext(key, lifetime, typeFactory, baseCacheKey, priority));
예제 #3
0
 public T GetService <T>(
     ServiceConfigurationKey key,
     Action <T, ServiceProvider, IServiceConfiguration> setup,
     Int32 setupOrder = 0,
     Type[] generics  = default)
     where T : class
 => this.GetService(key, setup as Action <Object, ServiceProvider, IServiceConfiguration>, setupOrder, generics) as T;
 public ServiceConfigurationServiceConfigurationKey(
     IServiceConfiguration serviceConfiguration,
     ServiceConfigurationKey serviceConfigurationKey)
 {
     ServiceConfiguration    = serviceConfiguration;
     ServiceConfigurationKey = serviceConfigurationKey;
 }
예제 #5
0
 public TKeyType GetService <TKeyType>(
     String keyName,
     Action <TKeyType, ServiceProvider, IServiceConfiguration> setup,
     Int32 setupOrder = 0,
     Type[] generics  = default)
     where TKeyType : class
 => this.GetService(ServiceConfigurationKey.From <TKeyType>(keyName), setup as Action <Object, ServiceProvider, IServiceConfiguration>, setupOrder, generics) as TKeyType;
예제 #6
0
 /// <summary>
 /// Registers a new ServiceConfiguration.
 /// </summary>
 /// <param name="key">The primary lookup key for the current service configuration.</param>
 /// <param name="lifetime">The default lifetime for the described service.</param>
 /// <param name="typeFactory">The <see cref="ITypeFactory.Type"/> to be used when building a new instance of this service.</param>
 /// <param name="cacheKeys">When a non <see cref="ServiceLifetime.Transient"/> service gets created the value will be linked within the defined cache keys so that any of the values will return the currently defined service.</param>
 /// <param name="priority">The priority value for this specific descriptor. All services will be sorted by priority when their the service provider is created.</param>
 public void RegisterServiceConfiguration(
     ServiceConfigurationKey key,
     ServiceLifetime lifetime,
     Type typeFactory,
     IEnumerable <ServiceConfigurationKey> cacheKeys,
     Int32 priority = 0)
 => this.Add(new ServiceConfigurationContext(key, lifetime, typeFactory, cacheKeys, priority));
예제 #7
0
        public Object GetService(
            ServiceConfigurationKey key,
            Action <Object, ServiceProvider, IServiceConfiguration> setup,
            Int32 setupOrder = 0,
            Type[] generics  = default)
        {
            // Implement some backwards compatibility with Microsoft's DI
            // For more info visit: https://github.com/aspnet/DependencyInjection/blob/d77b090567a1e6ad9a5bb5fd05f4bdcf281d4185/src/DI/ServiceLookup/CallSiteFactory.cs#L95

            // Check the recieved key directly...
            if (_primaryActiveService.TryGetValue(key, out _manager))
            {
                return(_manager.GetInstance(setup, setupOrder));
            }
            else if (_registeredServices.TryGetValue(key, out _services))
            {
                return(_services[0].GetInstance(this, generics, setup, setupOrder));
            }

            // Attempt to get constructed generic type services...
            key = key.TryGetGenericKey(out generics);
            if (_primaryActiveService.TryGetValue(key, out _manager))
            {
                return(_manager.GetInstance(setup, setupOrder));
            }
            else if (_registeredServices.TryGetValue(key, out _services))
            {
                return(_services[0].GetInstance(this, generics, setup, setupOrder));
            }


            // Attempt to create an enumerable instance based on the lookup key...
            return(this.TryCreateEnumerable(key, setup, setupOrder, generics));
        }
예제 #8
0
 public void Service <T>(
     ServiceConfigurationKey key,
     out T instance,
     Action <Object, ServiceProvider, IServiceConfiguration> setup,
     Int32 setupOrder = 0,
     Type[] generics  = default)
     where T : class
 => instance = this.GetService(key, setup, setupOrder, generics) as T;
예제 #9
0
 /// <summary>
 /// Determine if the current <see cref="ServiceConfigurationKey"/> inherits
 /// a recieved <see cref="ServiceConfigurationKey"/> value.
 /// </summary>
 /// <param name="parent"></param>
 /// <returns></returns>
 public Boolean Inherits(ServiceConfigurationKey parent)
 {
     return((
                parent.Type.IsAssignableFrom(this.Type) ||
                (
                    parent.Type.IsGenericTypeDefinition &&
                    this.Type.IsSubclassOfRawGeneric(parent.Type)
                )
                ) &&
            this.Name.StartsWith(parent.Name));
 }
예제 #10
0
 internal ComponentConfiguration(
     ComponentConfigurationContext context,
     Dictionary <ServiceConfigurationKey, IServiceConfiguration[]> serviceConfigurations,
     IEnumerable <ComponentFilter> componentFilters)
 {
     this.EntityServiceConfigurationKey = context.EntityServiceConfigurationKey;
     this.ComponentServiceConfiguration = serviceConfigurations[context.ComponentServiceConfigurationKey][0];
     this.ComponentFilters = componentFilters
                             .Where(f => context.ComponentServiceConfigurationKey.Inherits(f.ComponentServiceConfigurationKey))
                             .OrderBy(f => f.Order)
                             .ToArray();
 }
예제 #11
0
        /// <summary>
        /// Return all <see cref="ServiceConfigurationKey"/> instances with possible
        /// <see cref="ServiceConfigurationKey.Type"/> ancestry between the recieved
        /// type.
        /// </summary>
        /// <param name="parent"></param>
        /// <returns></returns>
        public IEnumerable <ServiceConfigurationKey> GetAncestors(ServiceConfigurationKey parent)
        {
            if (this.Inherits(parent))
            {
                foreach (Type ancestor in this.Type.GetAncestors(parent.Type))
                {
                    yield return(new ServiceConfigurationKey(ancestor, this.Name));
                }
            }
            ;

            yield return(this);
        }
예제 #12
0
        public ComponentFilter(
            ServiceConfigurationKey componentServiceConfigurationKey,
            Func <IEntity, ServiceProvider, Type, Boolean> method,
            Func <IServiceConfiguration, IServiceConfiguration, Boolean> validator,
            Int32 order)
        {
            ExceptionHelper.ValidateAssignableFrom <IComponent>(componentServiceConfigurationKey.Type);

            this.ComponentServiceConfigurationKey = componentServiceConfigurationKey;
            this.Method    = method;
            this.Validator = validator ?? DefaultValidator;
            this.Order     = order;
        }
예제 #13
0
        /// <summary>
        /// Loosly based on Microsoft's DI.
        /// See original here: https://github.com/aspnet/DependencyInjection/blob/d77b090567a1e6ad9a5bb5fd05f4bdcf281d4185/src/DI/ServiceLookup/CallSiteFactory.cs#L130
        /// </summary>
        /// <param name="key"></param>
        /// <param name="setup"></param>
        /// <param name="setupOrder"></param>
        /// <returns></returns>
        private Object TryCreateEnumerable(
            ServiceConfigurationKey key,
            Type[] generics)
        {
            if (key.Type == typeof(IEnumerable <>) && generics.Length == 1)
            {
                var configurations = _registeredServices
                                     .Where(kvp => generics[0].IsAssignableFrom(kvp.Key.Type))
                                     .SelectMany(kvp => kvp.Value);

                return(typeof(Enumerable)
                       .GetMethod("Cast")
                       .MakeGenericMethod(generics[0])
                       .Invoke(null, new object[] {
                    configurations.Select(c => c.GetInstance(this, default))
                }));
예제 #14
0
 /// <summary>
 /// Register a new component to an entity.
 /// </summary>
 /// <param name="componentServiceConfigurationKey">The component's key</param>
 /// <param name="entityServiceConfigurationKey">The entity's key</param>
 public void RegisterComponent(
     ServiceConfigurationKey componentServiceConfigurationKey,
     ServiceConfigurationKey entityServiceConfigurationKey)
 => this.Add(new ComponentConfigurationContext(componentServiceConfigurationKey, entityServiceConfigurationKey));
예제 #15
0
 object IServiceProvider.GetService(Type serviceType)
 => this.GetService(ServiceConfigurationKey.From(serviceType));
예제 #16
0
 public void Service <T>(
     ServiceConfigurationKey key,
     out T instance,
     Type[] generics = default)
     where T : class
 => instance = this.GetService(key, generics) as T;
예제 #17
0
 public TKey GetService <TKey>(
     Action <TKey, ServiceProvider, IServiceConfiguration> setup,
     Int32 setupOrder = 0,
     Type[] generics  = default)
     where TKey : class
 => this.GetService(ServiceConfigurationKey.From <TKey>(), setup as Action <Object, ServiceProvider, IServiceConfiguration>, setupOrder, generics) as TKey;
예제 #18
0
 public TKey GetService <TKey>(
     Type[] generics = default)
     where TKey : class
 => this.GetService(ServiceConfigurationKey.From <TKey>(), generics) as TKey;
예제 #19
0
 /// <summary>
 /// Register a new component to an entity.
 /// </summary>
 /// <typeparam name="TComponentKey">The component's key</typeparam>
 /// <typeparam name="TEntityKey">The entity's key</typeparam>
 public void RegisterComponent <TComponentKey, TEntityKey>()
     where TComponentKey : class, IComponent
     where TEntityKey : class, IEntity
 => this.RegisterComponent(ServiceConfigurationKey.From <TComponentKey>(), ServiceConfigurationKey.From <TEntityKey>());
예제 #20
0
 public void RegisterSetup <TKey>(
     Action <TKey, ServiceProvider, IServiceConfiguration> method,
     Int32 order = 0)
     where TKey : class
 => this.Add(new SetupAction(ServiceConfigurationKey.From <TKey>(), (i, p, c) => method(i as TKey, p, c), order));
예제 #21
0
 public void RegisterSetup(
     ServiceConfigurationKey key,
     Action <Object, ServiceProvider, IServiceConfiguration> method,
     Int32 order = 0)
 => this.Add(new SetupAction(key, method, order));
예제 #22
0
 /// <summary>
 /// Registers a new transient ServiceConfiguration.
 /// </summary>
 /// <typeparam name="TKey">The primary lookup key type for the current service configuration.</typeparam>
 /// <param name="typeFactory">The <see cref="ITypeFactory.Type"/> to be used when building a new instance of this service.</param>
 /// <param name="baseCacheKey">The minimum cache key. All ancestors between <paramref name="baseCacheKey"/> and <paramref name="key"/> will be used as <see cref="ServiceConfigurationContext.CacheKeys"/>.</param>
 /// <param name="priority">The priority value for this specific descriptor. All services will be sorted by priority when their the service provider is created.</param>
 public void RegisterTransient <TKey>(
     Type typeFactory,
     ServiceConfigurationKey baseCacheKey,
     Int32 priority = 0)
 => this.RegisterServiceConfiguration <TKey>(ServiceLifetime.Transient, typeFactory, baseCacheKey, priority);
예제 #23
0
 public T GetService <T>(
     ServiceConfigurationKey key,
     Type[] generics = default)
     where T : class
 => this.GetService(key, generics) as T;
예제 #24
0
 /// <summary>
 /// Register a new component to an entity.
 /// </summary>
 /// <typeparam name="TComponentKeyType">The component's key type</typeparam>
 /// <typeparam name="TEntityKeyType">The entity's key type</typeparam>
 /// <param name="componentKeyName">The component's key name</param>
 /// <param name="entityKeyName">The entity's key name</param>
 public void RegisterComponent <TComponentKeyType, TEntityKeyType>(
     String componentKeyName,
     String entityKeyName)
     where TComponentKeyType : class, IComponent
     where TEntityKeyType : class, IEntity
 => this.RegisterComponent(ServiceConfigurationKey.From <TComponentKeyType>(componentKeyName), ServiceConfigurationKey.From <TEntityKeyType>(entityKeyName));
예제 #25
0
 public ComponentFilter(
     ServiceConfigurationKey componentServiceConfigurationKey,
     Func <IEntity, ServiceProvider, Type, Boolean> method,
     Int32 order) : this(componentServiceConfigurationKey, method, ComponentFilter.DefaultValidator, order)
 {
 }
예제 #26
0
 public TKeyType GetService <TKeyType>(
     String keyName,
     Type[] generics = default)
     where TKeyType : class
 => this.GetService(ServiceConfigurationKey.From <TKeyType>(keyName), generics) as TKeyType;
예제 #27
0
 public void RegisterComponentFilter(
     ServiceConfigurationKey componentServiceConfigurationKey,
     Func <IEntity, ServiceProvider, Type, Boolean> method,
     Int32 order = 0)
 => this.Add(new ComponentFilter(componentServiceConfigurationKey, method, order));
예제 #28
0
 public void RegisterSetup <TKeyType>(
     String keyName,
     Action <TKeyType, ServiceProvider, IServiceConfiguration> method,
     Int32 order = 0)
     where TKeyType : class
 => this.Add(new SetupAction(ServiceConfigurationKey.From <TKeyType>(keyName), (i, p, c) => method(i as TKeyType, p, c), order));
예제 #29
0
        internal ServiceProvider(ServiceCollection services)
        {
            // Construct all relevant ITypeFactory instances.
            _typeFactories = services.TypeFactories
                             .GroupBy(tf => tf.Type)
                             .Select(g => g.OrderByDescending(tf => tf.Priority).First())
                             .Select(tf => tf.CreateTypeFactory(services.BuilderActions))
                             .ToDictionary(tf => tf.Type, tf => tf);

            // Construct all IServiceConfiguration instances.
            _registeredServices = services.ServiceConfigurations
                                  .OrderByDescending(sc => sc.Priority)
                                  .Select(sc => sc.CreateServiceConfiguration(_typeFactories, services.SetupActions))
                                  .GroupBy(sc => sc.Key)
                                  .ToDictionary(g => g.Key, g => g.ToArray());

            // Construct all ComponentConfiguration instances.
            _componentConfigurations = services.ComponentConfigurations
                                       .Select(c => c.CreateComponentConfiguration(_registeredServices, services.ComponentFilters))
                                       .GroupBy(c => c.EntityServiceConfigurationKey)
                                       .ToDictionary(g => g.Key, g => g.ToArray());

            // Add placeholders for every registered service type with no configurations
            foreach (ServiceConfigurationKey key in _registeredServices.Keys.Where(k => k.Inherits(ServiceConfigurationKey.From <IEntity>())))
            {
                if (!_componentConfigurations.ContainsKey(key))
                {
                    _componentConfigurations[key] = new ComponentConfiguration[0];
                }
            }

            _primaryActiveService = new Dictionary <ServiceConfigurationKey, IServiceManager>();
            _activeServices       = new Dictionary <ServiceConfigurationServiceConfigurationKey, IServiceManager>();


            this.IsRoot = true;
            this.Root   = this;
        }
예제 #30
0
 /// <summary>
 /// Registers a new transient ServiceConfiguration.
 /// </summary>
 /// <param name="key">The primary lookup key for the current service configuration.</param>
 /// <param name="typeFactory">The <see cref="ITypeFactory.Type"/> to be used when building a new instance of this service.</param>
 /// <param name="priority">The priority value for this specific descriptor. All services will be sorted by priority when their the service provider is created.</param>
 public void RegisterTransient(
     ServiceConfigurationKey key,
     Type typeFactory = default,
     Int32 priority   = 0)
 => this.RegisterServiceConfiguration(key, ServiceLifetime.Transient, typeFactory, priority);