// Note that the 'implementationType' could in fact be a service type as well and it is allowed // for the implementationType to equal TService. This will happen when someone does the following: // container.Collections.Register<ILogger>(typeof(ILogger)); private InstanceProducer GetOrCreateInstanceProducer(Type implementationType) { // If the implementationType is explicitly registered (using a Register call) we select this // producer (but we skip any implicit registrations or anything that is assignable, since // there could be more than one and it would be unclear which one to pick). InstanceProducer producer = this.GetExplicitRegisteredInstanceProducer(implementationType); // If that doesn't result in a producer, we request a registration using unregistered type // resolution, were we prevent concrete types from being created by the container, since // the creation of concrete type would 'pollute' the list of registrations, and might result // in two registrations (since below we need to create a new instance producer out of it), // and that might cause duplicate diagnostic warnings. if (producer == null) { producer = this.GetInstanceProducerThroughUnregisteredTypeResolution(implementationType); } // If that still hasn't resulted in a producer, we create a new producer and return (or throw // an exception in case the implementation type is not a concrete type). if (producer == null) { return(this.CreateNewExternalProducer(implementationType)); } // If there is such a producer registered we return a new one with the service type. // This producer will be automatically registered as external producer. if (producer.ServiceType == typeof(TService)) { return(producer); } return(new InstanceProducer(typeof(TService), new ExpressionRegistration(producer.BuildExpression(), this.container))); }
// This extension method is equivalent to the following registration, for each and every T: // container.Register<Lazy<T>>(() => new Lazy<T>(() => container.GetInstance<T>())); // This is useful for consumers that have a dependency on a service that is expensive to create, but // not always needed. // This mimics the behavior of Autofac and Ninject 3. In Autofac this behavior is default. public static void AllowResolvingLazyFactories(this Container container) { container.ResolveUnregisteredType += (sender, e) => { if (e.UnregisteredServiceType.IsGenericType && e.UnregisteredServiceType.GetGenericTypeDefinition() == typeof(Lazy <>)) { Type serviceType = e.UnregisteredServiceType.GetGenericArguments()[0]; InstanceProducer registration = container.GetRegistration(serviceType, true); Type funcType = typeof(Func <>).MakeGenericType(serviceType); Type lazyType = typeof(Lazy <>).MakeGenericType(serviceType); var factoryDelegate = Expression.Lambda(funcType, registration.BuildExpression()).Compile(); var lazyConstructor = ( from ctor in lazyType.GetConstructors() where ctor.GetParameters().Length == 1 where ctor.GetParameters()[0].ParameterType == funcType select ctor) .Single(); e.Register(Expression.New(lazyConstructor, Expression.Constant(factoryDelegate))); } }; }
private static void _resolvingLazyServicesHandler(object sender, UnregisteredTypeEventArgs e) { var type = e.UnregisteredServiceType; var container = sender as Container; if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Lazy <>)) { return; } Type serviceType = type.GetGenericArguments().First(); InstanceProducer registration = container .GetRegistration(serviceType, true); registration.Registration.SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent, "Ignored during automatic Lazy Registration"); Type funcType = typeof(Func <>).MakeGenericType(serviceType); Type lazyType = typeof(Lazy <>).MakeGenericType(serviceType); var funcExpression = Expression.Lambda(funcType, registration.BuildExpression()); var lazyDelegate = Expression.Lambda(lazyType, Expression.New(lazyType.GetConstructor(new[] { funcType }), funcExpression)).Compile(); e.Register(Expression.Constant(lazyDelegate)); }
public static void AllowResolvingFuncFactories(this ContainerOptions options) { options.Container.ResolveUnregisteredType += (s, e) => { var type = e.UnregisteredServiceType; if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Func <>)) { return; } Type serviceType = type.GetGenericArguments().First(); InstanceProducer registration = null; try { registration = options.Container.GetRegistration(serviceType, true); } catch (ActivationException) { serviceType = serviceType.GetInterfaces().FirstOrDefault(); registration = options.Container.GetRegistration(serviceType, true); } Type funcType = typeof(Func <>).MakeGenericType(serviceType); var factoryDelegate = Expression.Lambda(funcType, registration.BuildExpression()).Compile(); e.Register(Expression.Constant(factoryDelegate)); }; }
private static void _resolvingFuncFactoriesHandler(object sender, UnregisteredTypeEventArgs e) { var type = e.UnregisteredServiceType; var container = sender as Container; if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Func <>)) { return; } Type serviceType = type.GetGenericArguments().First(); InstanceProducer producer = container .GetRegistration(serviceType, true); producer.Registration.SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent, "Ignored during automatic Func Registration"); Type funcType = typeof(Func <>).MakeGenericType(serviceType); var factoryDelegate = Expression.Lambda(funcType, producer.BuildExpression()).Compile(); var registration = Lifestyle.Singleton.CreateRegistration(funcType, () => factoryDelegate, (Container)sender); e.Register(registration); }
/// <summary> /// Creates a <see cref="SimpleInjectorServiceHost"/> for a specified type of service with a specific /// base address. /// </summary> /// <returns> /// A <see cref="SimpleInjectorServiceHost"/> for the type of service specified with a specific base /// address. /// </returns> /// <param name="serviceType"> /// Specifies the type of service to host. /// </param> /// <param name="baseAddresses"> /// The <see cref="T:System.Array"/> of type <see cref="T:System.Uri"/> that contains the base /// addresses for the service hosted. /// </param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="serviceType"/> is a null /// reference.</exception> protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { Requires.IsNotNull(serviceType, nameof(serviceType)); if (container == null) { throw new InvalidOperationException("The operation failed. Please call the " + typeof(SimpleInjectorServiceHostFactory).FullName + ".SetContainer(Container) method " + "supplying the application's " + typeof(Container).FullName + " instance during " + "application startup (for instance inside the Application_Start event of the Global.asax). " + "In case you're running on non-HTTP protocols such as net.tcp and net.pipe that is " + "supported by the Windows Activation Service (WAS), please see the WCF integration " + "documentation: https://simpleinjector.org/wcf."); } InstanceProducer producer = container.GetRegistration(serviceType, true); // Force building the expression tree. Decorators and interceptors might be applied at this point, // causing the lifestyle and registration properties to change. producer.BuildExpression(); Type implementationType = producer.Registration.ImplementationType; return(HasInstanceContextModeSingle(implementationType) ? new SimpleInjectorServiceHost(container, GetSingletonInstance(producer), baseAddresses) : new SimpleInjectorServiceHost(container, serviceType, implementationType, baseAddresses)); }
// This extension method is equivalent to the following registration, for each and every T: // container.Register<Lazy<T>>(() => new Lazy<T>(() => container.GetInstance<T>())); // This is useful for consumers that have a dependency on a service that is expensive to create, but // not always needed. // This mimics the behavior of Autofac and Ninject 3. In Autofac this behavior is default. public static void AllowResolvingLazyFactories(this Container container) { container.ResolveUnregisteredType += (sender, e) => { if (e.UnregisteredServiceType.IsClosedTypeOf(typeof(Lazy <>))) { Type serviceType = e.UnregisteredServiceType.GetGenericArguments()[0]; InstanceProducer registration = container.GetRegistration(serviceType, true); Type funcType = typeof(Func <>).MakeGenericType(serviceType); var factoryDelegate = Expression.Lambda(funcType, registration.BuildExpression()).Compile(); var lazyConstructor = ( from ctor in e.UnregisteredServiceType.GetConstructors() where ctor.GetParameters().Length == 1 where ctor.GetParameters()[0].ParameterType == funcType select ctor) .Single(); var expression = Expression.New(lazyConstructor, Expression.Constant(factoryDelegate)); var lazyRegistration = registration.Lifestyle.CreateRegistration( serviceType: e.UnregisteredServiceType, instanceCreator: Expression.Lambda <Func <object> >(expression).Compile(), container: container); e.Register(lazyRegistration); } }; }
private static IEnumerable <Type> GetExpressionTypes(InstanceProducer instanceProducer) { var expression = instanceProducer.BuildExpression(); var visitor = new TypeExpressionVisitor(); visitor.Visit(expression); return(visitor.Types); }
public Expression BuildExpression(InjectionConsumerInfo consumer) { Requires.IsNotNull(consumer, "consumer"); InstanceProducer producer = this.GetInstanceProducerFor(consumer); // When the instance producer is invalid, this call will fail with an expressive exception. return(producer.BuildExpression()); }
public Expression BuildParameterExpression(ParameterInfo parameter) { Requires.IsNotNull(parameter, "parameter"); InstanceProducer producer = this.GetInstanceProducerFor(parameter); // When the instance producer is invalid, this call will fail with an expressive exception. return(producer.BuildExpression()); }
private static Expression BuildInterceptorExpression <TInterceptor>(Container container) where TInterceptor : class { InstanceProducer interceptorRegistration = container.GetRegistration(typeof(TInterceptor)); if (interceptorRegistration == null) { // This will throw an ActivationException container.GetInstance <TInterceptor>(); } return(interceptorRegistration.BuildExpression()); }
public InstanceProducer GetInstanceProducer(InjectionConsumerInfo consumer, bool throwOnFailure) { InstanceProducer producer = this.defaultBehavior.GetInstanceProducer(consumer, throwOnFailure); List <PredicatePair> pairs; if (this.MustApplyContextualDecorator(consumer.Target.TargetType, out pairs)) { return(this.ApplyDecorator(consumer.Target, producer.BuildExpression(), pairs)); } return(producer); }
public void BuildExpression_WithAutoVerificationEnabledOnAcyclicGraph_ShouldNotCauseACyclicGraphException() { // Arrange var container = ContainerFactory.New(); container.Options.EnableAutoVerification = true; container.Register <ICommand, ConcreteCommand>(new AsyncScopedLifestyle()); InstanceProducer producer = container.GetRegistration(typeof(ICommand)); // Act // NOTE: I had to change the places in InstanceProducer where the container was locked, to prevent // this test from failing. producer.BuildExpression(); }
// This extension method is equivalent to the following registration, for each and every T: // container.RegisterInstance<Func<T>>(() => container.GetInstance<T>()); // This is useful for consumers that need to create multiple instances of a dependency. // This mimics the behavior of Autofac. In Autofac this behavior is default. public static void AllowResolvingFuncFactories(this Container container) { container.ResolveUnregisteredType += (sender, e) => { if (e.UnregisteredServiceType.IsClosedTypeOf(typeof(Func <>))) { Type serviceType = e.UnregisteredServiceType.GetGenericArguments()[0]; InstanceProducer registration = container.GetRegistration(serviceType, true); var factoryDelegate = Expression.Lambda( e.UnregisteredServiceType, registration.BuildExpression()).Compile(); e.Register(Expression.Constant(factoryDelegate)); } }; }
public void BuildExpression_ManuallyCompiledToDelegate_CanBeExecutedSuccessfully() { // Arrange var container = ContainerFactory.New(); container.Register <ICommand, ConcreteCommand>(new AsyncScopedLifestyle()); // Creating the instance for type ICommand failed. The configuration is invalid. // The type ConcreteCommand is directly or indirectly depending on itself. // The cyclic graph contains the following types: ConcreteCommand. // Verification was triggered because Container.Options.EnableAutoVerification was enabled. // To prevent the container from being verified on first resolve, set the value to false. InstanceProducer producer = container.GetRegistration(typeof(ICommand)); Expression expression = producer.BuildExpression(); var factory = Expression.Lambda <Func <ICommand> >(expression).Compile(); using (AsyncScopedLifestyle.BeginScope(container)) { // Act factory(); } }