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