// 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)));
        }
예제 #2
0
        // 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)));
                }
            };
        }
예제 #3
0
        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));
            };
        }
예제 #5
0
        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);
        }
예제 #6
0
        /// <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));
        }
예제 #7
0
        // 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);
                }
            };
        }
예제 #8
0
    private static IEnumerable <Type> GetExpressionTypes(InstanceProducer instanceProducer)
    {
        var expression = instanceProducer.BuildExpression();
        var visitor    = new TypeExpressionVisitor();

        visitor.Visit(expression);
        return(visitor.Types);
    }
예제 #9
0
        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());
        }
예제 #10
0
        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();
        }
예제 #14
0
        // 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();
            }
        }