Ejemplo n.º 1
0
 /// <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));
 }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        /// <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);
        }
Ejemplo n.º 4
0
        /// <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);
        }
Ejemplo n.º 5
0
        /// <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));
        }
Ejemplo n.º 6
0
        /// <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));
        }
Ejemplo n.º 7
0
        /// <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);
        }
Ejemplo n.º 8
0
        /// <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);
        }
Ejemplo n.º 9
0
        /// <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);
        }
Ejemplo n.º 10
0
        /// <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);
        }
Ejemplo n.º 11
0
        /// <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);
        }
Ejemplo n.º 12
0
        /// <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);
            }
        }
Ejemplo n.º 13
0
        /// <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);
            }
        }
Ejemplo n.º 14
0
        /// <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);
        }
Ejemplo n.º 15
0
        /// <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);
        }
Ejemplo n.º 16
0
        /// <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);
        }
Ejemplo n.º 17
0
 /// <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;
Ejemplo n.º 19
0
 /// <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);
 }
Ejemplo n.º 20
0
 /// <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)));
 }