private IServiceProvider CreateServiceProviderCore(IEnumerable <ICodeGenerator> codeGenerators, ILogger logger, Action <ILogger, string, Exception> log4GenerateCode) { var generatedTypes = new List <GeneratedTypeEntry>(); var generationContext = new CodeGenerationContext(); generationContext.WriteLines("using System;"); generationContext.WriteLines("using System.Reflection;"); generationContext.WriteLines("using System.Threading.Tasks;"); generationContext.WriteLines("using Microsoft.Extensions.DependencyInjection;"); generationContext.WriteLines(""); generationContext.WriteLines("namespace Dora.Interception.CodeGeneration"); using (generationContext.CodeBlock()) { foreach (var service in _services) { foreach (var generator in codeGenerators) { if (generator.TryGenerate(service, generationContext, out var proxyTypeNames)) { generatedTypes.Add(new GeneratedTypeEntry(service, proxyTypeNames !, generator)); break; } } } } log4GenerateCode(logger, generationContext.SourceCode, null !); if (generatedTypes.Any()) { var compilation = CSharpCompilation.Create("Dora.Interception.CodeGeneration") .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, optimizationLevel: OptimizationLevel.Release)) .AddSyntaxTrees(SyntaxFactory.ParseSyntaxTree(generationContext.SourceCode)) .AddReferences(generationContext.References.Select(it => MetadataReference.CreateFromFile(it.Location))); Assembly outputAssembly; using var stream = new MemoryStream(); var compilationResult = compilation.Emit(stream); if (!compilationResult.Success) { var error = string.Join(Environment.NewLine, compilationResult.Diagnostics); throw new InterceptionException($"It fails to generate proxy class. \n {error}"); } var bytes = stream.ToArray(); outputAssembly = Assembly.Load(bytes); foreach (var entry in generatedTypes) { var proxyTypes = entry.ProxyTypeNames.Select(it => outputAssembly.GetType(it)).ToArray(); entry.CodeGenerator.RegisterProxyType(_services, entry.ServiceDescriptor, proxyTypes !); } } _services.Replace(ServiceDescriptor.Singleton <IServiceLifetimeProvider> (new ServiceLifetimeProvider(_services))); var serviceProvider = _services.BuildServiceProvider(_serviceProviderOptions); ((ApplicationServicesAccessor)serviceProvider.GetRequiredService <IApplicationServicesAccessor>()).ApplicationServices = serviceProvider; MethodInvokerBuilder.Instance = serviceProvider.GetRequiredService <IMethodInvokerBuilder>(); return(serviceProvider); }