private async Task <ViewCompilerWorkItem> CreateRuntimeCompilationWorkItem(string templateKey)
        {
            RazorLightProjectItem projectItem = null;

            if (_razorLightOptions.DynamicTemplates.TryGetValue(templateKey, out string templateContent))
            {
                projectItem = new TextSourceRazorProjectItem(templateKey, templateContent);
            }
            else
            {
                string normalizedKey = GetNormalizedKey(templateKey);
                projectItem = await _razorProject.GetItemAsync(normalizedKey);
            }

            if (!projectItem.Exists)
            {
                throw new TemplateNotFoundException($"Project can not find template with key {projectItem.Key}");
            }

            return(new ViewCompilerWorkItem()
            {
                SupportsCompilation = true,

                ProjectItem = projectItem,
                NormalizedKey = projectItem.Key,
                ExpirationToken = projectItem.ExpirationToken,
            });
        }
        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
            });
        }
示例#3
0
        /// <summary>
        /// Parses the template specified by <paramref name="projectItem"/>.
        /// </summary>
        /// <param name="projectItem">The <see cref="RazorLightProjectItem"/>.</param>
        /// <returns>The <see cref="IGeneratedRazorTemplate"/>.</returns>
        public async Task <IGeneratedRazorTemplate> GenerateCodeAsync(RazorLightProjectItem projectItem)
        {
            if (projectItem == null)
            {
                throw new ArgumentNullException(nameof(projectItem));
            }

            if (!projectItem.Exists)
            {
                throw new InvalidOperationException($"{nameof(RazorLightProjectItem)} of type " +
                                                    $"{projectItem.GetType().FullName} with key {projectItem.Key} does not exist.");
            }

            RazorCodeDocument codeDocument = await CreateCodeDocumentAsync(projectItem);

            ProjectEngine.Process(codeDocument);

            RazorCSharpDocument document = codeDocument.GetCSharpDocument();

            if (document.Diagnostics.Count > 0)
            {
                var builder = new StringBuilder();
                builder.AppendLine("Failed to generate Razor template. See \"Diagnostics\" property for more details");

                foreach (RazorDiagnostic d in document.Diagnostics)
                {
                    builder.AppendLine($"- {d.GetMessage()}");
                }

                throw new TemplateGenerationException(builder.ToString(), document.Diagnostics);
            }

            return(new GeneratedRazorTemplate(projectItem, document));
        }
        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 GeneratedRazorTemplate(RazorLightProjectItem projectItem, RazorCSharpDocument cSharpDocument)
        {
            if (projectItem == null)
            {
                throw new ArgumentNullException(nameof(projectItem));
            }

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

            ProjectItem    = projectItem;
            CSharpDocument = cSharpDocument;
        }
        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
            });
        }
示例#7
0
        /// <summary>
        /// Parses the template specified by the project item <paramref name="key"/>.
        /// </summary>
        /// <param name="key">The template path.</param>
        /// <returns>The <see cref="IGeneratedRazorTemplate"/>.</returns>
        public async Task <IGeneratedRazorTemplate> GenerateCodeAsync(string key)
        {
            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentException();
            }

            if (Project == null)
            {
                string _message = $"Can not resolve a content for the template \"{key}\" as there is no project set. " +
                                  "You can only render a template by passing it's content directly via string using corresponding function overload";

                throw new InvalidOperationException(_message);
            }

            RazorLightProjectItem projectItem = await Project.GetItemAsync(key).ConfigureAwait(false);

            return(await GenerateCodeAsync(projectItem));
        }
示例#8
0
        private async Task <ViewCompilerWorkItem> CreateRuntimeCompilationWorkItem(string normalizedKey)
        {
            RazorLightProjectItem projectItem = null;

            if (_razorLightOptions.DynamicTemplates.TryGetValue(normalizedKey, out string templateContent))
            {
                projectItem = new TextSourceRazorProjectItem(normalizedKey, templateContent);
            }
            else
            {
                projectItem = await _razorProject.GetItemAsync(normalizedKey);
            }

            if (!projectItem.Exists)
            {
                // If the file doesn't exist, we can't do compilation right now - we still want to cache
                // the fact that we tried. This will allow us to retrigger compilation if the view file
                // is added.
                return(new ViewCompilerWorkItem()
                {
                    // We don't have enough information to compile
                    SupportsCompilation = false,

                    Descriptor = new CompiledTemplateDescriptor()
                    {
                        TemplateKey = normalizedKey,
                        ExpirationToken = projectItem.ExpirationToken,
                    },

                    // We can try again if the file gets created.
                    ExpirationToken = projectItem.ExpirationToken,
                });
            }

            return(new ViewCompilerWorkItem()
            {
                SupportsCompilation = true,

                ProjectItem = projectItem,
                NormalizedKey = normalizedKey,
                ExpirationToken = projectItem.ExpirationToken,
            });
        }
        /// <summary>
        /// Generates a <see cref="RazorCodeDocument"/> for the specified <paramref name="projectItem"/>.
        /// </summary>
        /// <param name="projectItem">The <see cref="RazorLightProjectItem"/>.</param>
        /// <returns>The created <see cref="RazorCodeDocument"/>.</returns>
        public virtual async Task <RazorCodeDocument> CreateCodeDocumentAsync(RazorLightProjectItem projectItem)
        {
            if (projectItem == null)
            {
                throw new ArgumentNullException(nameof(projectItem));
            }

            if (!projectItem.Exists)
            {
                throw new InvalidOperationException($"Project can not find template with key {projectItem.Key}");
            }

            using (var stream = projectItem.Read())
            {
                RazorSourceDocument source = RazorSourceDocument.ReadFrom(stream, projectItem.Key);
                IEnumerable <RazorSourceDocument> imports = await GetImportsAsync(projectItem);

                return(RazorCodeDocument.Create(source, imports));
            }
        }
示例#10
0
        /// <summary>
        /// Gets <see cref="RazorSourceDocument"/> that are applicable to the specified <paramref name="projectItem"/>.
        /// </summary>
        /// <param name="projectItem">The <see cref="RazorLightProjectItem"/>.</param>
        /// <returns>The sequence of applicable <see cref="RazorSourceDocument"/>.</returns>
        public virtual async Task <IEnumerable <RazorSourceDocument> > GetImportsAsync(RazorLightProjectItem projectItem)
        {
            if (projectItem == null)
            {
                throw new ArgumentNullException(nameof(projectItem));
            }

            if (projectItem is TextSourceRazorProjectItem)
            {
                return(Enumerable.Empty <RazorSourceDocument>());
            }

            var result = new List <RazorSourceDocument>();

            IEnumerable <RazorLightProjectItem> importProjectItems = await Project.GetImportsAsync(projectItem.Key);

            foreach (var importItem in importProjectItems)
            {
                if (importItem.Exists)
                {
                    using (var stream = importItem.Read())
                    {
                        result.Insert(0, RazorSourceDocument.ReadFrom(stream, null));
                    }
                }
            }

            if (Namespaces != null)
            {
                RazorSourceDocument namespacesImports = GetNamespacesImports();
                if (namespacesImports != null)
                {
                    result.Insert(0, namespacesImports);
                }
            }

            if (DefaultImports != null)
            {
                result.Insert(0, DefaultImports);
            }

            return(result);
        }
        internal async Task <TemplateNotFoundException> CreateTemplateNotFoundException(RazorLightProjectItem projectItem)
        {
            var msg = $"{nameof(RazorLightProjectItem)} of type {projectItem.GetType().FullName} with key {projectItem.Key} could not be found by the " +
                      $"{ nameof(RazorLightProject)} of type { _razorProject.GetType().FullName} and does not exist in dynamic templates. ";

            var propNames = $"\"{nameof(TemplateNotFoundException.KnownDynamicTemplateKeys)}\" and \"{nameof(TemplateNotFoundException.KnownProjectTemplateKeys)}\"";

            if (_razorLightOptions.EnableDebugMode ?? false)
            {
                msg += $"See the {propNames} properties for known template keys.";

                var dynamicKeys = _razorLightOptions.DynamicTemplates.Keys.ToList();

                var projectKeys = await _razorProject.GetKnownKeysAsync();

                projectKeys = projectKeys == null?Enumerable.Empty <string>() : projectKeys.ToList();

                return(new TemplateNotFoundException(msg, dynamicKeys, projectKeys));
            }
            else
            {
                msg += $"Set {nameof(RazorLightOptions)}.{nameof(RazorLightOptions.EnableDebugMode)} to true to allow " +
                       $"the {propNames} properties on this exception to be set.";

                return(new TemplateNotFoundException(msg));
            }
        }