/// <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));
/// <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));
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; }
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;
/// <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));
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)); }
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;
/// <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)); }
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(); }
/// <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); }
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; }
/// <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)) }));
/// <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));
object IServiceProvider.GetService(Type serviceType) => this.GetService(ServiceConfigurationKey.From(serviceType));
public void Service <T>( ServiceConfigurationKey key, out T instance, Type[] generics = default) where T : class => instance = this.GetService(key, generics) as T;
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;
public TKey GetService <TKey>( Type[] generics = default) where TKey : class => this.GetService(ServiceConfigurationKey.From <TKey>(), generics) as TKey;
/// <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>());
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));
public void RegisterSetup( ServiceConfigurationKey key, Action <Object, ServiceProvider, IServiceConfiguration> method, Int32 order = 0) => this.Add(new SetupAction(key, method, order));
/// <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);
public T GetService <T>( ServiceConfigurationKey key, Type[] generics = default) where T : class => this.GetService(key, generics) as T;
/// <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));
public ComponentFilter( ServiceConfigurationKey componentServiceConfigurationKey, Func <IEntity, ServiceProvider, Type, Boolean> method, Int32 order) : this(componentServiceConfigurationKey, method, ComponentFilter.DefaultValidator, order) { }
public TKeyType GetService <TKeyType>( String keyName, Type[] generics = default) where TKeyType : class => this.GetService(ServiceConfigurationKey.From <TKeyType>(keyName), generics) as TKeyType;
public void RegisterComponentFilter( ServiceConfigurationKey componentServiceConfigurationKey, Func <IEntity, ServiceProvider, Type, Boolean> method, Int32 order = 0) => this.Add(new ComponentFilter(componentServiceConfigurationKey, method, order));
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));
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; }
/// <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);