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); } }
/// <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<T></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<Type>)</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()); }
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); }
/// <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<T></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<Type>)</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()); }