protected virtual CompiledTemplateDescriptor CompileAndEmit(RazorLightProjectItem projectItem)
        {
            Assembly assembly = default(Assembly);

            if (_razorLightOptions.BinaryCache.TryGetValue($"{projectItem.Key}-Assembly", out var assemblyBinary) && _razorLightOptions.BinaryCache.TryGetValue($"{projectItem.Key}-Assembly", out var pdbBinary))
            {
                assembly = _compiler.Emit(assemblyBinary, pdbBinary);
            }
            else
            {
                IGeneratedRazorTemplate generatedTemplate =
                    _razorSourceGenerator.GenerateCodeAsync(projectItem).GetAwaiter().GetResult();
                var compileResult = _compiler.Compile(generatedTemplate);
                _razorLightOptions.BinaryCache.CreateEntry($"{projectItem.Key}-Assembly", compileResult.AssemblyStream);
                _razorLightOptions.BinaryCache.CreateEntry($"{projectItem.Key}-Pdb", compileResult.PdbStream);
                assembly = _compiler.Emit(compileResult.AssemblyStream, compileResult.PdbStream);
            }

            // Anything we compile from source will use Razor 2.1 and so should have the new metadata.
            var loader    = new RazorCompiledItemLoader();
            var item      = loader.LoadItems(assembly).SingleOrDefault();
            var attribute = assembly.GetCustomAttribute <RazorLightTemplateAttribute>();

            return(new CompiledTemplateDescriptor()
            {
                Item = item,
                TemplateKey = projectItem.Key,
                TemplateAttribute = attribute
            });
        }
        protected async Task <TemplateFactoryResult> CompileAsync(IGeneratedRazorTemplate razorTemplate)
        {
            CompiledTemplateDescriptor templateDescriptor = await templateCompiler.CompileAsync(razorTemplate);

            templateDescriptor.ExpirationToken = razorTemplate.ProjectItem.ExpirationToken;

            string templateKey = templateDescriptor.TemplateKey;

            if (templateDescriptor.TemplateAttribute != null)
            {
                Type compiledType = templateDescriptor.TemplateAttribute.TemplateType;

                var newExpression              = Expression.New(compiledType);
                var keyProperty                = compiledType.GetTypeInfo().GetProperty(nameof(ITemplatePage.Key));
                var propertyBindExpression     = Expression.Bind(keyProperty, Expression.Constant(templateKey));
                var objectInitializeExpression = Expression.MemberInit(newExpression, propertyBindExpression);

                var pageFactory = Expression
                                  .Lambda <Func <ITemplatePage> >(objectInitializeExpression)
                                  .Compile();
                return(new TemplateFactoryResult(templateDescriptor, pageFactory));
            }
            else
            {
                throw new RazorLightException($"Template {templateKey} is corrupted or invalid");
            }
        }
        protected CompiledTemplateDescriptor CompileAndEmit(IGeneratedRazorTemplate razorTemplate)
        {
            if (razorTemplate == null)
            {
                throw new ArgumentNullException(nameof(razorTemplate));
            }

            string assemblyName = Path.GetRandomFileName();
            var    compilation  = CreateCompilation(razorTemplate.GeneratedCode, assemblyName);

            using (var assemblyStream = new MemoryStream())
                using (var pdbStream = new MemoryStream())
                {
                    var result = compilation.Emit(
                        assemblyStream,
                        pdbStream,
                        options: EmitOptions);

                    if (!result.Success)
                    {
                        List <Diagnostic> errorsDiagnostics = result.Diagnostics
                                                              .Where(d => d.IsWarningAsError || d.Severity == DiagnosticSeverity.Error)
                                                              .ToList();

                        StringBuilder builder = new StringBuilder();
                        builder.AppendLine("Failed to compile generated Razor template:");

                        var errorMessages = new List <string>();
                        foreach (Diagnostic diagnostic in errorsDiagnostics)
                        {
                            FileLinePositionSpan lineSpan = diagnostic.Location.SourceTree.GetMappedLineSpan(diagnostic.Location.SourceSpan);
                            string errorMessage           = diagnostic.GetMessage();
                            string formattedMessage       = $"- ({lineSpan.StartLinePosition.Line}:{lineSpan.StartLinePosition.Character}) {errorMessage}";

                            errorMessages.Add(formattedMessage);
                            builder.AppendLine(formattedMessage);
                        }

                        builder.AppendLine("\nSee CompilationErrors for detailed information");

                        throw new TemplateCompilationException(builder.ToString(), errorMessages);
                    }

                    assemblyStream.Seek(0, SeekOrigin.Begin);
                    pdbStream.Seek(0, SeekOrigin.Begin);

                    var assembly           = Assembly.Load(assemblyStream.ToArray(), pdbStream.ToArray());
                    var templateDescriptor = new CompiledTemplateDescriptor()
                    {
                        TemplateKey       = razorTemplate.TemplateKey,
                        TemplateAttribute = assembly.GetCustomAttribute <RazorLightTemplateAttribute>(),
                    };

                    return(templateDescriptor);
                }
        }
        public async Task <TemplateFactoryResult> CreateFactoryAsync(RazorLightProjectItem projectItem)
        {
            if (projectItem == null)
            {
                throw new ArgumentNullException(nameof(projectItem));
            }

            IGeneratedRazorTemplate razorTemplate = await sourceGenerator.GenerateCodeAsync(projectItem).ConfigureAwait(false);

            return(await CompileAsync(razorTemplate));
        }
        public Task <CompiledTemplateDescriptor> CompileAsync(IGeneratedRazorTemplate razorTemplate)
        {
            if (razorTemplate == null)
            {
                throw new ArgumentNullException(nameof(razorTemplate));
            }

            MemoryCacheEntryOptions cacheEntryOptions;
            TaskCompletionSource <CompiledTemplateDescriptor> compilationTaskSource = null;
            Task <CompiledTemplateDescriptor> cacheEntry;

            string templateKey = razorTemplate.TemplateKey;

            lock (_locker)
            {
                if (_cache.TryGetValue(templateKey, out cacheEntry))
                {
                    return(cacheEntry);
                }

                cacheEntryOptions = new MemoryCacheEntryOptions();
                if (razorTemplate.ProjectItem.ExpirationToken != null)
                {
                    cacheEntryOptions.ExpirationTokens.Add(razorTemplate.ProjectItem.ExpirationToken);
                }

                compilationTaskSource = new TaskCompletionSource <CompiledTemplateDescriptor>();

                cacheEntry = _cache.Set(templateKey, compilationTaskSource.Task, cacheEntryOptions);
            }

            if (compilationTaskSource != null)
            {
                Debug.Assert(cacheEntryOptions != null);

                try
                {
                    var descriptor = CompileAndEmit(razorTemplate);
                    compilationTaskSource.SetResult(descriptor);
                }
                catch (Exception ex)
                {
                    compilationTaskSource.SetException(ex);
                }
            }

            return(cacheEntry);
        }
        public Assembly CompileAndEmit(IGeneratedRazorTemplate razorTemplate)
        {
            TkDebug.AssertArgumentNull(razorTemplate, nameof(razorTemplate), this);

            string assemblyName = Path.GetRandomFileName();
            var    compilation  = CreateCompilation(razorTemplate.GeneratedCode, assemblyName);

            using (var assemblyStream = new MemoryStream())
                using (var pdbStream = new MemoryStream())
                {
                    var result = compilation.Emit(assemblyStream, pdbStream, options: EmitOptions);

                    if (!result.Success)
                    {
                        List <Diagnostic> errorsDiagnostics = result.Diagnostics
                                                              .Where(d => d.IsWarningAsError || d.Severity == DiagnosticSeverity.Error)
                                                              .ToList();
                        throw new RazorCompilerException(errorsDiagnostics,
                                                         razorTemplate.TemplateKey, razorTemplate.GeneratedCode);
                        ////StringBuilder builder = new StringBuilder();
                        ////builder.AppendLine("Failed to compile generated Razor template:");

                        ////var errorMessages = new List<string>();
                        ////foreach (Diagnostic diagnostic in errorsDiagnostics)
                        ////{
                        ////    FileLinePositionSpan lineSpan = diagnostic.Location.SourceTree.GetMappedLineSpan(diagnostic.Location.SourceSpan);
                        ////    string errorMessage = diagnostic.GetMessage();
                        ////    string formattedMessage = $"- ({lineSpan.StartLinePosition.Line}:{lineSpan.StartLinePosition.Character}) {errorMessage}";

                        ////    errorMessages.Add(formattedMessage);
                        ////    builder.AppendLine(formattedMessage);
                        ////}

                        ////builder.AppendLine("\nSee CompilationErrors for detailed information");

                        ////throw new TemplateCompilationException(builder.ToString(), errorMessages, this);
                    }
                    razorTemplate.ProjectItem.SaveAssembly(assemblyStream, pdbStream);

                    assemblyStream.Seek(0, SeekOrigin.Begin);
                    pdbStream.Seek(0, SeekOrigin.Begin);

                    var assembly = Assembly.Load(assemblyStream.ToArray(), pdbStream.ToArray());

                    return(assembly);
                }
        }
        protected virtual CompiledTemplateDescriptor CompileAndEmit(RazorLightProjectItem projectItem)
        {
            IGeneratedRazorTemplate generatedTemplate = _razorSourceGenerator.GenerateCodeAsync(projectItem).GetAwaiter().GetResult();
            Assembly assembly = _compiler.CompileAndEmit(generatedTemplate);

            // Anything we compile from source will use Razor 2.1 and so should have the new metadata.
            var loader    = new RazorCompiledItemLoader();
            var item      = loader.LoadItems(assembly).SingleOrDefault();
            var attribute = assembly.GetCustomAttribute <RazorLightTemplateAttribute>();

            return(new CompiledTemplateDescriptor()
            {
                Item = item,
                TemplateKey = projectItem.Key,
                TemplateAttribute = attribute
            });
        }
        public async Task <TemplateFactoryResult> CreateFactoryAsync(string templateKey)
        {
            if (templateKey == null)
            {
                throw new ArgumentNullException(nameof(templateKey));
            }

            IGeneratedRazorTemplate razorTemplate = null;

            if (options.DynamicTemplates.TryGetValue(templateKey, out string templateContent))
            {
                var projectItem = new TextSourceRazorProjectItem(templateKey, templateContent);
                razorTemplate = await sourceGenerator.GenerateCodeAsync(projectItem).ConfigureAwait(false);
            }
            else
            {
                razorTemplate = await sourceGenerator.GenerateCodeAsync(templateKey).ConfigureAwait(false);
            }

            return(await CompileAsync(razorTemplate));
        }