Beispiel #1
0
        private void RegisterDecoratorCore(
            Type serviceType,
            Type decoratorType,
            Predicate <DecoratorPredicateContext>?predicate = null,
            Lifestyle?lifestyle = null)
        {
            Requires.IsNotNull(serviceType, nameof(serviceType));
            Requires.IsNotNull(decoratorType, nameof(decoratorType));

            Requires.IsNotPartiallyClosed(serviceType, nameof(serviceType));
            Requires.ServiceTypeIsNotClosedWhenImplementationIsOpen(serviceType, decoratorType);
            Requires.ServiceOrItsGenericTypeDefinitionIsAssignableFromImplementation(
                serviceType, decoratorType, nameof(serviceType));

            Requires.ImplementationHasSelectableConstructor(this, decoratorType, nameof(decoratorType));
            Requires.IsDecorator(this, serviceType, decoratorType, nameof(decoratorType));
            Requires.DecoratorIsNotAnOpenGenericTypeDefinitionWhenTheServiceTypeIsNot(
                serviceType, decoratorType, nameof(decoratorType));

            Requires.OpenGenericTypeDoesNotContainUnresolvableTypeArguments(
                serviceType, decoratorType, nameof(decoratorType));

            var interceptor = new DecoratorInterceptor(
                new DecoratorExpressionInterceptorData(
                    this, serviceType, decoratorType, predicate, lifestyle ?? this.SelectionBasedLifestyle));

            this.ExpressionBuilt += interceptor.ExpressionBuilt;
        }
        /// <summary>
        /// Registers all concrete, non-generic, public and internal types in the given set of
        /// <paramref name="assemblies"/> that implement the given <paramref name="openGenericServiceType"/>
        /// with the supplied <paramref name="lifestyle"/>.
        /// <see cref="TypesToRegisterOptions.IncludeDecorators">Decorators</see> and
        /// <see cref="TypesToRegisterOptions.IncludeGenericTypeDefinitions">generic type definitions</see>
        /// will be excluded from registration, while
        /// <see cref="TypesToRegisterOptions.IncludeComposites">composites</see> are included.
        /// </summary>
        /// <param name="openGenericServiceType">The definition of the open generic type.</param>
        /// <param name="assemblies">A list of assemblies that will be searched.</param>
        /// <param name="lifestyle">The lifestyle to register instances with.</param>
        /// <exception cref="ArgumentNullException">Thrown when one of the arguments contain a null
        /// reference.</exception>
        /// <exception cref="ArgumentException">Thrown when <paramref name="openGenericServiceType"/> is not
        /// an open generic type.</exception>
        /// <exception cref="InvalidOperationException">Thrown when the given set of
        /// <paramref name="assemblies"/> contain multiple types that implement the same
        /// closed generic version of the given <paramref name="openGenericServiceType"/>.</exception>
        public void Register(
            Type openGenericServiceType, IEnumerable <Assembly> assemblies, Lifestyle lifestyle)
        {
            Requires.IsNotNull(openGenericServiceType, nameof(openGenericServiceType));
            Requires.IsNotNull(lifestyle, nameof(lifestyle));
            Requires.IsNotNull(assemblies, nameof(assemblies));

            Requires.IsGenericType(
                openGenericServiceType,
                nameof(openGenericServiceType),
                guidance: StringResources.SuppliedTypeIsNotGenericExplainingAlternativesWithAssemblies);

            Requires.IsNotPartiallyClosed(openGenericServiceType, nameof(openGenericServiceType));

            Requires.IsOpenGenericType(
                openGenericServiceType,
                nameof(openGenericServiceType),
                guidance: StringResources.SuppliedTypeIsNotOpenGenericExplainingAlternativesWithAssemblies);

            var results =
                this.GetNonGenericTypesToRegisterForOneToOneMapping(openGenericServiceType, assemblies);

            this.Register(openGenericServiceType, results.ImplementationTypes, lifestyle);

            this.AddSkippedDecorators(openGenericServiceType, results.SkippedDecorators);
        }
        /// <summary>
        /// Registers all supplied <paramref name="implementationTypes"/> based on the closed-generic version
        /// of the given <paramref name="openGenericServiceType"/> with the given <paramref name="lifestyle"/>.
        /// </summary>
        /// <param name="openGenericServiceType">The definition of the open generic type.</param>
        /// <param name="implementationTypes">A list types to be registered.</param>
        /// <param name="lifestyle">The lifestyle to register instances with.</param>
        /// <exception cref="ArgumentNullException">Thrown when one of the arguments contain a null
        /// reference (Nothing in VB).</exception>
        /// <exception cref="ArgumentException">Thrown when <paramref name="openGenericServiceType"/> is not
        /// an open generic type or when one of the supplied types from the
        /// <paramref name="implementationTypes"/> collection does not derive from
        /// <paramref name="openGenericServiceType"/>.</exception>
        /// <exception cref="InvalidOperationException">Thrown when the given set of
        /// <paramref name="implementationTypes"/> contain multiple types that implement the same
        /// closed generic version of the given <paramref name="openGenericServiceType"/>.</exception>
        public void Register(Type openGenericServiceType, IEnumerable <Type> implementationTypes, Lifestyle lifestyle)
        {
            Requires.IsNotNull(openGenericServiceType, nameof(openGenericServiceType));
            Requires.IsNotNull(lifestyle, nameof(lifestyle));
            Requires.IsNotNull(implementationTypes, nameof(implementationTypes));
            Requires.IsGenericType(openGenericServiceType, nameof(openGenericServiceType),
                                   guidance: StringResources.SuppliedTypeIsNotGenericExplainingAlternativesWithTypes);
            Requires.IsNotPartiallyClosed(openGenericServiceType, nameof(openGenericServiceType));
            Requires.IsOpenGenericType(openGenericServiceType, nameof(openGenericServiceType),
                                       guidance: StringResources.SuppliedTypeIsNotOpenGenericExplainingAlternativesWithTypes);

            implementationTypes = implementationTypes.Distinct().ToArray();

            Requires.DoesNotContainNullValues(implementationTypes, nameof(implementationTypes));
            Requires.CollectionDoesNotContainOpenGenericTypes(implementationTypes, nameof(implementationTypes));
            Requires.ServiceIsAssignableFromImplementations(openGenericServiceType, implementationTypes,
                                                            nameof(implementationTypes), typeCanBeServiceType: false);

            var mappings =
                from mapping in BatchMapping.Build(openGenericServiceType, implementationTypes)
                let registration = lifestyle.CreateRegistration(mapping.ImplementationType, this)
                                   from serviceType in mapping.ClosedServiceTypes
                                   select new { serviceType, registration };

            foreach (var mapping in mappings)
            {
                this.AddRegistration(mapping.serviceType, mapping.registration);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Conditionally registers that an instance of <paramref name="implementationType"/> will be
        /// returned every time a <paramref name="serviceType"/> is requested and where the supplied
        /// <paramref name="predicate"/> returns true. The instance is cached according to the supplied
        /// <paramref name="lifestyle"/>. The predicate will only be evaluated a finite number of times; the
        /// predicate is unsuited for making decisions based on runtime conditions.
        /// </summary>
        /// <param name="serviceType">The base type or interface to register. This can be an open-generic type.</param>
        /// <param name="implementationType">The actual type that will be returned when requested.</param>
        /// <param name="lifestyle">The lifestyle that defines how returned instances are cached.</param>
        /// <param name="predicate">The predicate that determines whether the
        /// <paramref name="implementationType"/> can be applied for the requested service type. This predicate
        /// can be used to build a fallback mechanism where multiple registrations for the same service type
        /// are made. Note that the predicate will be called a finite number of times and its result will be cached
        /// for the lifetime of the container. It can't be used for selecting a type based on runtime conditions.
        /// </param>
        /// <exception cref="ArgumentNullException">Thrown when one of the arguments is a null reference
        /// (Nothing in VB).</exception>
        /// <exception cref="ArgumentException">Thrown when <paramref name="serviceType"/> and
        /// <paramref name="implementationType"/> are not a generic type or when <paramref name="serviceType"/>
        /// is a partially-closed generic type.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Thrown when this container instance is locked and can not be altered.
        /// </exception>
        public void RegisterConditional(
            Type serviceType,
            Type implementationType,
            Lifestyle lifestyle,
            Predicate <PredicateContext> predicate)
        {
            Requires.IsNotNull(serviceType, nameof(serviceType));
            Requires.IsNotNull(implementationType, nameof(implementationType));
            Requires.IsNotNull(lifestyle, nameof(lifestyle));
            Requires.IsNotNull(predicate, nameof(predicate));
            Requires.IsNotPartiallyClosed(serviceType, nameof(serviceType), nameof(implementationType));

            Requires.ServiceOrItsGenericTypeDefinitionIsAssignableFromImplementation(
                serviceType, implementationType, nameof(serviceType));

            Requires.ImplementationHasSelectableConstructor(
                this, implementationType, nameof(implementationType));

            Requires.OpenGenericTypeDoesNotContainUnresolvableTypeArguments(
                serviceType, implementationType, nameof(implementationType));

            if (serviceType.ContainsGenericParameters())
            {
                this.RegisterOpenGeneric(serviceType, implementationType, lifestyle, predicate);
            }
            else
            {
                var registration = lifestyle.CreateRegistration(implementationType, this);
                this.RegisterConditional(serviceType, registration, predicate);
            }
        }
        /// <summary>
        /// Returns all concrete types that are located in the supplied <paramref name="assemblies"/>
        /// and implement or inherit from the supplied <paramref name="serviceType"/> and match the specified
        /// <paramref name="options."/>. <paramref name="serviceType"/> can be an open-generic type.
        /// </summary>
        /// <remarks>
        /// Use this method when you need influence the types that are registered using
        /// <see cref="Register(System.Type, IEnumerable{System.Reflection.Assembly})">Register</see>.
        /// The <b>Register</b> overloads that take a collection of <see cref="Assembly"/>
        /// objects use this method internally to get the list of types that need to be registered. Instead of
        /// calling  such overload, you can call an overload that takes a list of <see cref="System.Type"/> objects
        /// and pass  in a filtered result from this <b>GetTypesToRegister</b> method.
        /// <code lang="cs"><![CDATA[
        /// var container = new Container();
        ///
        /// var assemblies = new[] { typeof(ICommandHandler<>).Assembly };
        /// var options = new TypesToRegisterOptions { IncludeGenericTypeDefinitions: true };
        /// var types = container.GetTypesToRegister(typeof(ICommandHandler<>), assemblies, options)
        ///     .Where(type => type.IsPublic);
        ///
        /// container.Register(typeof(ICommandHandler<>), types);
        /// ]]></code>
        /// This example calls the <b>GetTypesToRegister</b> method to request a list of concrete implementations
        /// of the <b>ICommandHandler&lt;T&gt;</b> interface from the assembly of that interface. After that
        /// all internal types are filtered out. This list is supplied to the
        /// <see cref="Container.Register(System.Type,IEnumerable{System.Type})">Register(Type, IEnumerable&lt;Type&gt;)</see>
        /// overload to finish the registration.
        /// </remarks>
        /// <param name="serviceType">The base type or interface to find derived types for. This can be both
        /// a non-generic and open-generic type.</param>
        /// <param name="assemblies">A list of assemblies that will be searched.</param>
        /// <param name="options">The options.</param>
        /// <returns>A collection of types.</returns>
        /// <exception cref="ArgumentNullException">Thrown when one of the arguments contain a null reference.
        /// </exception>
        public IEnumerable <Type> GetTypesToRegister(
            Type serviceType, IEnumerable <Assembly> assemblies, TypesToRegisterOptions options)
        {
            Requires.IsNotNull(serviceType, nameof(serviceType));
            Requires.IsNotNull(assemblies, nameof(assemblies));
            Requires.IsNotNull(options, nameof(options));
            Requires.IsNotPartiallyClosed(serviceType, nameof(serviceType));

            return(this.GetTypesToRegisterInternal(serviceType, assemblies, options).ToArray());
        }
Beispiel #6
0
        private void RegisterOpenGeneric(Type serviceType, Type implementationType,
                                         Lifestyle lifestyle, Predicate <PredicateContext> predicate = null)
        {
            Requires.IsGenericType(serviceType, nameof(serviceType));
            Requires.IsNotPartiallyClosed(serviceType, nameof(serviceType));
            Requires.ServiceOrItsGenericTypeDefinitionIsAssignableFromImplementation(serviceType,
                                                                                     implementationType, nameof(serviceType));
            Requires.OpenGenericTypeDoesNotContainUnresolvableTypeArguments(serviceType,
                                                                            implementationType, nameof(implementationType));

            this.GetOrCreateRegistrationalEntry(serviceType)
            .AddGeneric(serviceType, implementationType, lifestyle, predicate);
        }
Beispiel #7
0
        /// <summary>
        /// Conditionally registers that an instance of the type returned from
        /// <paramref name="implementationTypeFactory"/> will be returned every time a
        /// <paramref name="serviceType"/> is requested and where the supplied <paramref name="predicate"/>
        /// returns true. The instance is cached according to the supplied
        /// <paramref name="lifestyle"/>. Both the <paramref name="predicate"/> and
        /// <paramref name="implementationTypeFactory"/> will only be evaluated a finite number of times;
        /// they unsuited for making decisions based on runtime conditions.
        /// </summary>
        /// <param name="serviceType">The base type or interface to register. This can be an open-generic type.</param>
        /// <param name="implementationTypeFactory">A factory that allows building Type objects that define the
        /// implementation type to inject, based on the given contextual information. The delegate is allowed
        /// to return (partially) open-generic types.</param>
        /// <param name="lifestyle">The lifestyle that defines how returned instances are cached.</param>
        /// <param name="predicate">The predicate that determines whether the registration can be applied for
        /// the requested service type. This predicate can be used to build a fallback mechanism where
        /// multiple registrations for the same service type are made.</param>
        /// <exception cref="ArgumentNullException">Thrown when one of the arguments is a null reference
        /// (Nothing in VB).</exception>
        /// <exception cref="ArgumentException">Thrown when <paramref name="serviceType"/> is a
        /// partially-closed generic type.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Thrown when this container instance is locked and can not be altered.
        /// </exception>
        public void RegisterConditional(
            Type serviceType,
            Func <TypeFactoryContext, Type> implementationTypeFactory,
            Lifestyle lifestyle,
            Predicate <PredicateContext> predicate)
        {
            Requires.IsNotNull(serviceType, nameof(serviceType));
            Requires.IsNotNull(implementationTypeFactory, nameof(implementationTypeFactory));
            Requires.IsNotNull(lifestyle, nameof(lifestyle));
            Requires.IsNotNull(predicate, nameof(predicate));
            Requires.IsNotPartiallyClosed(serviceType, nameof(serviceType));

            this.GetOrCreateRegistrationalEntry(serviceType)
            .Add(serviceType, implementationTypeFactory, lifestyle, predicate);
        }
        /// <summary>
        /// Registers all concrete, non-generic, public and internal types in the given set of
        /// <paramref name="assemblies"/> that implement the given <paramref name="openGenericServiceType"/>
        /// with the supplied <paramref name="lifestyle"/>.
        /// </summary>
        /// <param name="openGenericServiceType">The definition of the open generic type.</param>
        /// <param name="assemblies">A list of assemblies that will be searched.</param>
        /// <param name="lifestyle">The lifestyle to register instances with.</param>
        /// <exception cref="ArgumentNullException">Thrown when one of the arguments contain a null
        /// reference (Nothing in VB).</exception>
        /// <exception cref="ArgumentException">Thrown when <paramref name="openGenericServiceType"/> is not
        /// an open generic type.</exception>
        /// <exception cref="InvalidOperationException">Thrown when the given set of
        /// <paramref name="assemblies"/> contain multiple types that implement the same
        /// closed generic version of the given <paramref name="openGenericServiceType"/>.</exception>
        public void Register(Type openGenericServiceType, IEnumerable <Assembly> assemblies, Lifestyle lifestyle)
        {
            Requires.IsNotNull(openGenericServiceType, "openGenericServiceType");
            Requires.IsNotNull(lifestyle, "lifestyle");
            Requires.IsNotNull(assemblies, "assemblies");
            Requires.IsGenericType(openGenericServiceType, "openGenericServiceType",
                                   guidance: StringResources.SuppliedTypeIsNotGenericExplainingAlternativesWithAssemblies);
            Requires.IsNotPartiallyClosed(openGenericServiceType, "openGenericServiceType");
            Requires.IsOpenGenericType(openGenericServiceType, "openGenericServiceType",
                                       guidance: StringResources.SuppliedTypeIsNotOpenGenericExplainingAlternativesWithAssemblies);

            var implementationTypes = this.GetTypesToRegister(openGenericServiceType, assemblies);

            this.Register(openGenericServiceType, implementationTypes, lifestyle);
        }
        /// <summary>
        /// Returns all concrete types that are located in the supplied <paramref name="assemblies"/>
        /// and implement or inherit from the supplied <paramref name="serviceType"/> and match the specified
        /// <paramref name="options."/>. <paramref name="serviceType"/> can be an open-generic type.
        /// </summary>
        /// <remarks>
        /// Use this method when you need influence the types that are registered using
        /// <see cref="Register(System.Type, IEnumerable{System.Reflection.Assembly})">Register</see>.
        /// The <b>Register</b> overloads that take a collection of <see cref="Assembly"/>
        /// objects use this method internally to get the list of types that need to be registered. Instead of
        /// calling  such overload, you can call an overload that takes a list of <see cref="System.Type"/> objects
        /// and pass  in a filtered result from this <b>GetTypesToRegister</b> method.
        /// <code lang="cs"><![CDATA[
        /// var container = new Container();
        ///
        /// var assemblies = new[] { typeof(ICommandHandler<>).Assembly };
        /// var options = new TypesToRegisterOptions { IncludeGenericTypeDefinitions: true };
        /// var types = container.GetTypesToRegister(typeof(ICommandHandler<>), assemblies, options)
        ///     .Where(type => !type.IsPublic);
        ///
        /// container.Register(typeof(ICommandHandler<>), types);
        /// ]]></code>
        /// This example calls the <b>GetTypesToRegister</b> method to request a list of concrete implementations
        /// of the <b>ICommandHandler&lt;T&gt;</b> interface from the assembly of that interface. After that
        /// all internal types are filtered out. This list is supplied to the
        /// <see cref="Container.Register(System.Type,IEnumerable{System.Type})">Register(Type, IEnumerable&lt;Type&gt;)</see>
        /// overload to finish the registration.
        /// </remarks>
        /// <param name="serviceType">The base type or interface to find derived types for. This can be both
        /// a non-generic and open-generic type.</param>
        /// <param name="assemblies">A list of assemblies that will be searched.</param>
        /// <param name="options">The options.</param>
        /// <returns>A collection of types.</returns>
        /// <exception cref="ArgumentNullException">Thrown when one of the arguments contain a null reference
        /// (Nothing in VB).</exception>
        public IEnumerable <Type> GetTypesToRegister(Type serviceType, IEnumerable <Assembly> assemblies,
                                                     TypesToRegisterOptions options)
        {
            Requires.IsNotNull(serviceType, nameof(serviceType));
            Requires.IsNotNull(assemblies, nameof(assemblies));
            Requires.IsNotNull(options, nameof(options));
            Requires.IsNotPartiallyClosed(serviceType, nameof(serviceType));

            var types =
                from assembly in assemblies.Distinct()
                where !assembly.IsDynamic
                from type in GetTypesFromAssembly(assembly)
                where Types.IsConcreteType(type)
                where options.IncludeGenericTypeDefinitions || !type.IsGenericTypeDefinition()
                where Types.ServiceIsAssignableFromImplementation(serviceType, type)
                let ctor = this.SelectImplementationTypeConstructorOrNull(type)
                           where ctor == null || options.IncludeDecorators || !Types.IsDecorator(serviceType, ctor)
                           where ctor == null || options.IncludeComposites || !Types.IsComposite(serviceType, ctor)
                           select type;

            return(types.ToArray());
        }