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