/// <summary>
        /// Creates a <see cref="ServiceProvider"/> containing services from the provided <see cref="IServiceCollection"/>
        /// optionally enabling scope validation.
        /// </summary>
        /// <param name="services">The <see cref="IServiceCollection"/> containing service descriptors.</param>
        /// <param name="options">
        /// Configures various service provider behaviors.
        /// </param>
        /// <returns>The <see cref="ServiceProvider"/>.</returns>
        public static ServiceProvider BuildServiceProvider(this IServiceCollection services, ServiceProviderOptions options)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            IServiceProviderEngine engine;

#if !NETSTANDARD2_1
            engine = new DynamicServiceProviderEngine(services);
#else
            if (RuntimeFeature.IsDynamicCodeCompiled)
            {
                engine = new DynamicServiceProviderEngine(services);
            }
            else
            {
                // Don't try to compile Expressions/IL if they are going to get interpreted
                engine = new RuntimeServiceProviderEngine(services);
            }
#endif

            return(new ServiceProvider(services, engine, options));
        }
Пример #2
0
        // We are not testing singleton here because singleton resolutions always got through
        // runtime resolver and there is no sense to eliminating call from there
        public void BuildExpressionElidesDisposableCaptureForNonDisposableServices(ServiceLifetime lifetime)
        {
            IServiceCollection descriptors = new ServiceCollection();

            descriptors.Add(ServiceDescriptor.Describe(typeof(ServiceA), typeof(ServiceA), lifetime));
            descriptors.Add(ServiceDescriptor.Describe(typeof(ServiceB), typeof(ServiceB), lifetime));
            descriptors.Add(ServiceDescriptor.Describe(typeof(ServiceC), typeof(ServiceC), lifetime));

            descriptors.AddScoped <ServiceB>();
            descriptors.AddTransient <ServiceC>();

            var disposables = new List <object>();
            var provider    = new DynamicServiceProviderEngine(descriptors);

            provider.Root._captureDisposableCallback = obj =>
            {
                disposables.Add(obj);
            };
            var callSite         = provider.CallSiteFactory.GetCallSite(typeof(ServiceC), new CallSiteChain());
            var compiledCallSite = CompileCallSite(callSite, provider);

            var serviceC = (ServiceC)compiledCallSite(provider.Root);

            Assert.Empty(disposables);
        }
Пример #3
0
        public void DoesNotThrowWhenServiceIsUsedAsEnumerableAndNotInOneCallSite()
        {
            var descriptors = new ServiceCollection();

            descriptors.AddTransient <ServiceA>();
            descriptors.AddTransient <ServiceD>();
            descriptors.AddTransient <ServiceE>();

            var provider = new DynamicServiceProviderEngine(descriptors);

            var callSite1       = provider.CallSiteFactory.GetCallSite(typeof(ServiceE), new CallSiteChain());
            var compileCallSite = CompileCallSite(callSite1, provider);

            Assert.NotNull(compileCallSite);
        }
Пример #4
0
        public void BuiltExpressionCanResolveNestedScopedService()
        {
            var descriptors = new ServiceCollection();

            descriptors.AddScoped <ServiceA>();
            descriptors.AddScoped <ServiceB>();
            descriptors.AddScoped <ServiceC>();

            var provider         = new DynamicServiceProviderEngine(descriptors, null);
            var callSite         = provider.CallSiteFactory.CreateCallSite(typeof(ServiceC), new CallSiteChain());
            var compiledCallSite = CompileCallSite(callSite, provider);

            var serviceC = (ServiceC)compiledCallSite(provider.Root);

            Assert.NotNull(serviceC.ServiceB.ServiceA);
            Assert.Equal(serviceC, Invoke(callSite, provider));
        }
Пример #5
0
        private ServiceProviderEngine GetEngine()
        {
            ServiceProviderEngine engine;

#if NETFRAMEWORK || NETSTANDARD2_0
            engine = new DynamicServiceProviderEngine(this);
#else
            if (RuntimeFeature.IsDynamicCodeCompiled)
            {
                engine = new DynamicServiceProviderEngine(this);
            }
            else
            {
                // Don't try to compile Expressions/IL if they are going to get interpreted
                engine = RuntimeServiceProviderEngine.Instance;
            }
#endif
            return(engine);
        }
Пример #6
0
        // We are not testing singleton here because singleton resolutions always got through
        // runtime resolver and there is no sense to eliminating call from there
        public void BuildExpressionElidesDisposableCaptureForEnumerableServices(ServiceLifetime lifetime)
        {
            IServiceCollection descriptors = new ServiceCollection();

            descriptors.Add(ServiceDescriptor.Describe(typeof(ServiceA), typeof(ServiceA), lifetime));
            descriptors.Add(ServiceDescriptor.Describe(typeof(ServiceD), typeof(ServiceD), lifetime));

            var disposables = new List <object>();
            var provider    = new DynamicServiceProviderEngine(descriptors, null);

            provider.Root._captureDisposableCallback = obj =>
            {
                disposables.Add(obj);
            };
            var callSite         = provider.CallSiteFactory.CreateCallSite(typeof(ServiceD), new HashSet <Type>());
            var compiledCallSite = CompileCallSite(callSite, provider);

            var serviceD = (ServiceD)compiledCallSite(provider.Root);

            Assert.Empty(disposables);
        }
Пример #7
0
        public void BuildExpressionAddsDisposableCaptureForDisposableServices(ServiceLifetime lifetime)
        {
            IServiceCollection descriptors = new ServiceCollection();

            descriptors.Add(ServiceDescriptor.Describe(typeof(ServiceA), typeof(DisposableServiceA), lifetime));
            descriptors.Add(ServiceDescriptor.Describe(typeof(ServiceB), typeof(DisposableServiceB), lifetime));
            descriptors.Add(ServiceDescriptor.Describe(typeof(ServiceC), typeof(DisposableServiceC), lifetime));

            var disposables = new List <object>();
            var provider    = new DynamicServiceProviderEngine(descriptors, null);

            provider.Root._captureDisposableCallback = obj =>
            {
                disposables.Add(obj);
            };
            var callSite         = provider.CallSiteFactory.CreateCallSite(typeof(ServiceC), new CallSiteChain());
            var compiledCallSite = CompileCallSite(callSite, provider);

            var serviceC = (DisposableServiceC)compiledCallSite(provider.Root);

            Assert.Equal(3, disposables.Count);
        }
Пример #8
0
        public void BuiltExpressionWillReturnResolvedServiceWhenAppropriate(
            ServiceDescriptor[] descriptors, Type serviceType, Func <object, object, bool> compare)
        {
            var provider = new DynamicServiceProviderEngine(descriptors, null);

            var callSite           = provider.CallSiteFactory.CreateCallSite(serviceType, new CallSiteChain());
            var collectionCallSite = provider.CallSiteFactory.CreateCallSite(typeof(IEnumerable <>).MakeGenericType(serviceType), new CallSiteChain());

            var compiledCallSite           = CompileCallSite(callSite, provider);
            var compiledCollectionCallSite = CompileCallSite(collectionCallSite, provider);

            var service1          = Invoke(callSite, provider);
            var service2          = compiledCallSite(provider.Root);
            var serviceEnumerator = ((IEnumerable)compiledCollectionCallSite(provider.Root)).GetEnumerator();

            Assert.NotNull(service1);
            Assert.True(compare(service1, service2));

            // Service can be IEnumerable resolved. The IEnumerable should have exactly one element.
            Assert.True(serviceEnumerator.MoveNext());
            Assert.True(compare(service1, serviceEnumerator.Current));
            Assert.False(serviceEnumerator.MoveNext());
        }
Пример #9
0
        public void BuiltExpressionRethrowsOriginalExceptionFromConstructor()
        {
            var descriptors = new ServiceCollection();

            descriptors.AddTransient <ClassWithThrowingEmptyCtor>();
            descriptors.AddTransient <ClassWithThrowingCtor>();
            descriptors.AddTransient <IFakeService, FakeService>();

            var provider = new DynamicServiceProviderEngine(descriptors);

            var callSite1         = provider.CallSiteFactory.GetCallSite(typeof(ClassWithThrowingEmptyCtor), new CallSiteChain());
            var compiledCallSite1 = CompileCallSite(callSite1, provider);

            var callSite2         = provider.CallSiteFactory.GetCallSite(typeof(ClassWithThrowingCtor), new CallSiteChain());
            var compiledCallSite2 = CompileCallSite(callSite2, provider);

            var ex1 = Assert.Throws <Exception>(() => compiledCallSite1(provider.Root));

            Assert.Equal(nameof(ClassWithThrowingEmptyCtor), ex1.Message);

            var ex2 = Assert.Throws <Exception>(() => compiledCallSite2(provider.Root));

            Assert.Equal(nameof(ClassWithThrowingCtor), ex2.Message);
        }