.NET Core中如何从Razor Engine模板提取Model键列表?
提取Razor模板中@Model的属性键列表
方法一:正则表达式(快速实现,适合简单模板)
对于结构相对简单的模板,可通过正则表达式匹配所有@Model.开头的属性访问,同时排除方法调用类的场景(如@Model.DoSomething())。
正则表达式与提取代码
using System.Text.RegularExpressions; using System.Linq; string template = @"<acord> <student> <firstName>@Model.StudentFirstName</firstName> <lastName>@Model.StudentLastName</lastName> @if(@Model.StudentPhone != null) { <phone>@Model.StudentPhone</phone> } </student> <parents> <firstName>@Model.parentFirstName</firstName> <lastName>@Model.parentLastName</lastName> </parents> </acord>"; // 匹配@Model.后接合法C#标识符,排除方法调用 var regex = new Regex(@"@Model\.([a-zA-Z_][a-zA-Z0-9_]+)(?!\()", RegexOptions.Compiled); var matches = regex.Matches(template); // 去重并整理结果 var modelKeys = matches.Cast<Match>() .Select(m => $"@Model.{m.Groups[1].Value}") .Distinct() .ToList(); // 输出提取的键 foreach (var key in modelKeys) { Console.WriteLine(key); }
这种方法优点是实现成本低,但无法处理复杂Razor语法(如嵌套属性@Model.Parent.Child、注释中的@Model引用等)。
方法二:Razor语法树解析(精准可靠,适合复杂模板)
如果模板包含条件判断、循环、嵌套属性等复杂逻辑,推荐使用官方Razor解析API生成语法树,遍历节点精准提取所有Model属性访问。
步骤1:安装依赖包
安装Microsoft.AspNetCore.Razor.Language NuGet包:
Install-Package Microsoft.AspNetCore.Razor.Language
步骤2:解析模板的代码实现
using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Intermediate; using Microsoft.CodeAnalysis.CSharp.Syntax; using System.Collections.Generic; using System.Linq; public static List<string> ExtractModelProperties(string razorTemplate) { var modelKeys = new HashSet<string>(); var engine = RazorEngine.Create(); var projectEngine = engine.Project.Create(); // 生成Razor文档并处理为中间节点 var document = projectEngine.CreateDocument("template.cshtml", razorTemplate); var intermediateNode = projectEngine.Process(document).GetIntermediateNode(); // 递归遍历语法树节点 TraverseNode(intermediateNode, modelKeys); return modelKeys.OrderBy(k => k).ToList(); } private static void TraverseNode(IntermediateNode node, HashSet<string> modelKeys) { if (node is CSharpCodeIntermediateNode codeNode) { // 解析C#代码片段,查找Model的成员访问表达式 var syntaxTree = Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(codeNode.Code); var root = syntaxTree.GetRoot(); var memberAccesses = root.DescendantNodes() .OfType<MemberAccessExpressionSyntax>() .Where(m => m.Expression is IdentifierNameSyntax identifier && identifier.Identifier.Text == "Model"); foreach (var access in memberAccesses) { // 处理嵌套属性,拼接完整路径 var pathSegments = new List<string> { "Model" }; var current = access; while (current != null) { pathSegments.Insert(1, current.Name.Identifier.Text); current = current.Expression as MemberAccessExpressionSyntax; } modelKeys.Add($"@{string.Join(".", pathSegments)}"); } } // 递归处理子节点 foreach (var child in node.Children) { TraverseNode(child, modelKeys); } }
使用示例
var template = @"<acord> <student> <firstName>@Model.StudentFirstName</firstName> <lastName>@Model.StudentLastName</lastName> @if(@Model.StudentPhone != null) { <phone>@Model.StudentPhone</phone> } </student> <parents> <firstName>@Model.parentFirstName</firstName> <lastName>@Model.parentLastName</lastName> <address>@Model.Parent.Address.Street</address> </parents> </acord>"; var keys = ExtractModelProperties(template); foreach (var key in keys) { Console.WriteLine(key); }
该方法能精准处理各种复杂Razor语法场景,是生产环境的可靠选择。
内容的提问来源于stack exchange,提问作者Harsh
相关产品推荐
相关产品推荐

