/// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="Lifecycle.Transient"/> service /// using the factory specified in <paramref name="implementationFactory"/> /// to the <paramref name="services"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="services">The <see cref="IRegistrationCollection"/>.</param> /// <param name="implementationFactory">The factory that creates the service.</param> public static void TryAddTransient <TService>( this IRegistrationCollection services, Func <IServiceProvider, TService> implementationFactory) where TService : class { services.TryAdd(RegistrationDescriptor.Transient(implementationFactory)); }
private bool TryCreateSelfBinding(Type type, string key, out IRegistrationCollection registrations) { registrations = null; if (type.IsAbstract || !type.IsClass) { return(false); } var injectAttribute = type.GetCustomAttribute <InjectAttribute>(true); if (injectAttribute != null && injectAttribute.Key != key) { return(false); } // Only allow types in our whitelisted assemblies // This stops us trying to charge off and create List<T> or some other BCL class which we don't have a hope in hell of creating // This in turn leads to some very hard-to-debug error cases where we descend into infinite recursion on some random type if (!this.autobindAssemblies.Contains(type.Assembly)) { return(false); } var typeKey = new TypeKey(type.TypeHandle, key); registrations = this.AddRegistration(typeKey, new TransientRegistration(new TypeCreator(type, this))); return(true); }
/// <summary> /// Adds an instance /// </summary> /// <typeparam name="TService"></typeparam> /// <param name="registry"></param> /// <param name="instance"></param> /// <returns></returns> public static IRegistrationCollection AddInstance <TService>(this IRegistrationCollection registry, TService instance) { var descriptor = RegistrationDescriptor.Singleton(typeof(TService), instance); registry.Add(descriptor); return(registry); }
/// <summary> /// If the given type is a Func{T}, get a registration which can create an instance of it /// </summary> private bool TryCreateFuncFactory(Type type, string key, out IRegistrationCollection registrations) { registrations = null; if (!type.IsGenericType) { return(false); } var genericType = type.GetGenericTypeDefinition(); var genericArguments = type.GetGenericArguments(); if (genericType == typeof(Func <>)) { var typeKey = new TypeKey(type.TypeHandle, key); foreach (var registration in this.GetRegistrations(new TypeKey(genericArguments[0].TypeHandle, key), true, genericArguments[0]).GetAll()) { registrations = this.AddRegistration(typeKey, new FuncRegistration(registration)); } } else { return(false); } return(true); }
/// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="Lifecycle.Transient"/> service /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="collection">The <see cref="IRegistrationCollection"/>.</param> public static void TryAddTransient <TService>(this IRegistrationCollection collection) where TService : class { if (collection is null) { throw new ArgumentNullException(nameof(collection)); } TryAddTransient(collection, typeof(TService), typeof(TService)); }
/// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="Lifecycle.Singleton"/> service /// implementation type specified in <typeparamref name="TImplementation"/> /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam> /// <param name="collection">The <see cref="IRegistrationCollection"/>.</param> public static void TryAddSingleton <TService, TImplementation>(this IRegistrationCollection collection) where TService : class where TImplementation : class, TService { if (collection is null) { throw new ArgumentNullException(nameof(collection)); } TryAddSingleton(collection, typeof(TService), typeof(TImplementation)); }
/// <summary> /// Given a generic type (e.g. IValidator{T}), tries to create a collection of IRegistrations which can implement it from the unbound generic registrations. /// For example, if someone bound an IValidator{} to Validator{}, and this was called with Validator{T}, the IRegistrationCollection would contain a Validator{T}. /// </summary> private bool TryCreateGenericTypesForUnboundGeneric(Type type, string key, out IRegistrationCollection registrations) { registrations = null; if (!type.IsGenericType || type.GenericTypeArguments.Length == 0) { return(false); } Type unboundGenericType = type.GetGenericTypeDefinition(); List <UnboundGeneric> unboundGenerics; if (!this.unboundGenerics.TryGetValue(new TypeKey(unboundGenericType.TypeHandle, key), out unboundGenerics)) { return(false); } foreach (var unboundGeneric in unboundGenerics) { // Consider this scenario: // interface IC<T, U> { } class C<T, U> : IC<U, T> { } // Then they ask for an IC<int, bool>. We need to give them a C<bool, int> // Search the ancestry of C for an IC (called implOfUnboundGenericType), then create a mapping which says that // U is a bool and T is an int by comparing this against 'type' - the IC<T, U> that's registered as the service // Then use this when making the type for C Type newType; if (unboundGeneric.Type == unboundGenericType) { newType = type; } else { var implOfUnboundGenericType = unboundGeneric.Type.GetBaseTypesAndInterfaces().Single(x => x.Name == unboundGenericType.Name); var mapping = implOfUnboundGenericType.GenericTypeArguments.Zip(type.GenericTypeArguments, (n, t) => new { Type = t, Name = n }); newType = unboundGeneric.Type.MakeGenericType(unboundGeneric.Type.GetTypeInfo().GenericTypeParameters.Select(x => mapping.Single(t => t.Name.Name == x.Name).Type).ToArray()); } // The binder should have made sure of this Debug.Assert(type.IsAssignableFrom(newType)); // Right! We've made a new generic type we can use var registration = unboundGeneric.CreateRegistrationForTypeAndKey(newType, key); // AddRegistration returns the IRegistrationCollection which was added/updated, so the one returned from the final // call to AddRegistration is the final IRegistrationCollection for this key registrations = this.AddRegistration(new TypeKey(type.TypeHandle, key), registration); } return(registrations != null); }
/// <summary> /// Adds the specified <typeparamref name="TService"/> as a <see cref="Lifecycle.Singleton"/> service /// with an instance specified in <paramref name="instance"/> /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <typeparam name="TService">The type of the service to add.</typeparam> /// <param name="collection">The <see cref="IRegistrationCollection"/>.</param> /// <param name="instance">The instance of the service to add.</param> public static void TryAddSingleton <TService>(this IRegistrationCollection collection, TService instance) where TService : class { if (collection is null) { throw new ArgumentNullException(nameof(collection)); } if (instance is null) { throw new ArgumentNullException(nameof(instance)); } var descriptor = RegistrationDescriptor.Singleton(typeof(TService), instance); TryAdd(collection, descriptor); }
/// <summary> /// Adds the specified <paramref name="descriptor"/> to the <paramref name="collection"/>. /// </summary> /// <param name="collection">The <see cref="IRegistrationCollection"/>.</param> /// <param name="descriptor">The <see cref="RegistrationDescriptor"/> to add.</param> /// <returns>A reference to the current instance of <see cref="IRegistrationCollection"/>.</returns> public static IRegistrationCollection Add( this IRegistrationCollection collection, RegistrationDescriptor descriptor) { if (collection is null) { throw new ArgumentNullException(nameof(collection)); } if (descriptor is null) { throw new ArgumentNullException(nameof(descriptor)); } collection.Add(descriptor); return(collection); }
/// <summary> /// Removes all services of type <paramef name="serviceType"/> in <see cref="IRegistrationCollection"/>. /// </summary> /// <param name="collection">The <see cref="IRegistrationCollection"/>.</param> /// <param name="serviceType">The service type to remove.</param> /// <returns></returns> public static IRegistrationCollection RemoveAll(this IRegistrationCollection collection, Type serviceType) { if (serviceType is null) { throw new ArgumentNullException(nameof(serviceType)); } for (var i = collection.Count - 1; i >= 0; i--) { var descriptor = collection[i]; if (descriptor.ServiceType == serviceType) { collection.RemoveAt(i); } } return(collection); }
/// <summary> /// Adds the specified <paramref name="service"/> as a <see cref="Lifecycle.Transient"/> service /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IRegistrationCollection"/>.</param> /// <param name="service">The type of the service to register.</param> public static void TryAddTransient( this IRegistrationCollection collection, Type service) { if (collection is null) { throw new ArgumentNullException(nameof(collection)); } if (service is null) { throw new ArgumentNullException(nameof(service)); } var descriptor = RegistrationDescriptor.Transient(service, service); TryAdd(collection, descriptor); }
/// <summary> /// Adds the specified <paramref name="descriptors"/> to the <paramref name="collection"/> if the /// service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IRegistrationCollection"/>.</param> /// <param name="descriptors">The <see cref="RegistrationDescriptor"/>s to add.</param> public static void TryAdd( this IRegistrationCollection collection, IEnumerable <RegistrationDescriptor> descriptors) { if (collection is null) { throw new ArgumentNullException(nameof(collection)); } if (descriptors is null) { throw new ArgumentNullException(nameof(descriptors)); } foreach (var d in descriptors) { collection.TryAdd(d); } }
/// <summary> /// Adds the specified <paramref name="descriptor"/> to the <paramref name="collection"/> if the /// service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IRegistrationCollection"/>.</param> /// <param name="descriptor">The <see cref="RegistrationDescriptor"/> to add.</param> public static void TryAdd( this IRegistrationCollection collection, RegistrationDescriptor descriptor) { if (collection is null) { throw new ArgumentNullException(nameof(collection)); } if (descriptor is null) { throw new ArgumentNullException(nameof(descriptor)); } if (!collection.Any(d => d.ServiceType == descriptor.ServiceType)) { collection.Add(descriptor); } }
/// <summary> /// Removes the first service in <see cref="IRegistrationCollection"/> with the same service type /// as <paramref name="descriptor"/> and adds <paramef name="descriptor"/> to the collection. /// </summary> /// <param name="collection">The <see cref="IRegistrationCollection"/>.</param> /// <param name="descriptor">The <see cref="RegistrationDescriptor"/> to replace with.</param> /// <returns></returns> public static IRegistrationCollection Replace( this IRegistrationCollection collection, RegistrationDescriptor descriptor) { if (collection is null) { throw new ArgumentNullException(nameof(collection)); } if (descriptor is null) { throw new ArgumentNullException(nameof(descriptor)); } var registeredRegistrationDescriptor = collection.FirstOrDefault(s => s.ServiceType == descriptor.ServiceType); if (registeredRegistrationDescriptor is object) { collection.Remove(registeredRegistrationDescriptor); } collection.Add(descriptor); return(collection); }
/// <summary> /// Adds the specified <paramref name="service"/> as a <see cref="Lifecycle.Singleton"/> service /// with the <paramref name="implementationType"/> implementation /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IRegistrationCollection"/>.</param> /// <param name="service">The type of the service to register.</param> /// <param name="implementationType">The implementation type of the service.</param> public static void TryAddSingleton( this IRegistrationCollection collection, Type service, Type implementationType) { if (collection is null) { throw new ArgumentNullException(nameof(collection)); } if (service is null) { throw new ArgumentNullException(nameof(service)); } if (implementationType is null) { throw new ArgumentNullException(nameof(implementationType)); } var descriptor = RegistrationDescriptor.Singleton(service, implementationType); TryAdd(collection, descriptor); }
/// <summary> /// Adds the specified <paramref name="service"/> as a <see cref="Lifecycle.Transient"/> service /// using the factory specified in <paramref name="implementationFactory"/> /// to the <paramref name="collection"/> if the service type hasn't already been registered. /// </summary> /// <param name="collection">The <see cref="IRegistrationCollection"/>.</param> /// <param name="service">The type of the service to register.</param> /// <param name="implementationFactory">The factory that creates the service.</param> public static void TryAddTransient( this IRegistrationCollection collection, Type service, Func <IServiceProvider, object> implementationFactory) { if (collection is null) { throw new ArgumentNullException(nameof(collection)); } if (service is null) { throw new ArgumentNullException(nameof(service)); } if (implementationFactory is null) { throw new ArgumentNullException(nameof(implementationFactory)); } var descriptor = RegistrationDescriptor.Transient(service, implementationFactory); TryAdd(collection, descriptor); }
/// <summary> /// Adds a transient lifecycle service /// </summary> /// <typeparam name="TService"></typeparam> /// <typeparam name="TImplementation"></typeparam> /// <param name="registry"></param> /// <returns></returns> public static IRegistrationCollection AddTransient <TService, TImplementation>(this IRegistrationCollection registry) where TImplementation : TService { registry.Add(RegistrationDescriptor.Transient(typeof(TService), typeof(TImplementation))); return(registry); }
/// <summary> /// Constructor /// </summary> /// <param name="serviceCollection"></param> public RegisterRegistrationDescriptionCollection(IRegistrationCollection serviceCollection) => _registrationCollection = serviceCollection;
/// <summary> /// Adds a scoped lifecycle service /// </summary> /// <param name="registry"></param> /// <param name="serviceType"></param> /// <param name="implementationType"></param> /// <returns></returns> public static IRegistrationCollection AddScoped(this IRegistrationCollection registry, Type serviceType, Type implementationType) { registry.Add(RegistrationDescriptor.Scoped(serviceType, implementationType)); return(registry); }
/// <summary> /// Removes all services of type <typeparamef name="T"/> in <see cref="IRegistrationCollection"/>. /// </summary> /// <param name="collection">The <see cref="IRegistrationCollection"/>.</param> /// <returns></returns> public static IRegistrationCollection RemoveAll <T>(this IRegistrationCollection collection) { return(RemoveAll(collection, typeof(T))); }