我正在寫一個ASP.NET/C#中的內容管理系統,該網站的模板是在html文件中定義的。我通過塊將參數傳遞給html文件。一個塊以[並以結束]開頭。有一些簡單模板的示例:模板解析和反射
<html>
<head>
<title>[Title]</title>
<meta name="description" content="[Description]" />
</head>
<body>
<h1>[Headline]</h1>
<p>[Text]</p>
</body>
</html>
現在,我有一個代表模板的類。對於例如模板類看起來是這樣的:
public class MyTemplate
{
public string Title
{
get;
set;
}
public string Description
{
get;
set;
}
public string Headline
{
get;
set;
}
public string Text
{
get;
set;
}
}
類可能是一類,我寫的,通過產生的Linq to SQL或只是任何類的類。
我創建了一個用屬性值替換塊的方法。我正在使用正則表達式來實現此目的:
public static string ParseTemplateFromObject(string input, object obj)
{
return Regex.Replace(input, @"\[(.*?)\]", new MatchEvaluator(delegate(Match match)
{
var blockName = match.Result("$1");
return obj.GetType().GetProperties().SingleOrDefault(p => p.Name.Equals(blockName, StringComparison.OrdinalIgnoreCase))
.GetValue(obj, null).ToString();
}), RegexOptions.Multiline);
}
...並且它正在工作。我使用GetProperties(),然後使用Linq代替GetProperty來防止區分大小寫。但是現在我又遇到了另一個問題,那就是當我想在塊中使用參數時。例如:我想創建一個垂直菜單。在系統菜單可垂直或水平:
[Menu Id=1, Direction="Vertical"]
所以,我決定,而不是獲取價值,從它的特性,這種類型的塊的調用方法,並提取它的價值。例如:
public class MyTemplate
{
...
public string Menu(int id, string direction)
{
string menu = ...;
return menu;
}
}
我伸出我的ParseTemplateFromObject
來支持這一點:
public static string ParseTemplateFromObject(string input, object obj)
{
return Regex.Replace(input, @"\[(.*?)\]", new MatchEvaluator(delegate(Match match)
{
var blockName = match.Result("$1");
var m = Regex.Match(blockName, "(?<Name>\\w+)=((?<Value>\\w+)|\"(?<Value>([^\"]*))\")");
if (m.Captures.Count > 0)
{
var method = obj.GetType().GetMethods().Single(p => p.Name.Equals(blockName.Substring(0, blockName.IndexOf(' '))
, StringComparison.OrdinalIgnoreCase));
var methodParameters = method.GetParameters();
var parameters = new object[methodParameters.Length];
while (m.Success)
{
var name = m.Groups["Name"].Value;
var value = m.Groups["Value"].Value;
var methodParameter = methodParameters.Single(p => p.Name.ToLower() == name.ToLower());
parameters[methodParameter.Position] =
Convert.ChangeType(value, methodParameter.ParameterType);
m = m.NextMatch();
}
return method.Invoke(obj, parameters).ToString();
}
else
{
return obj.GetType().GetProperties().SingleOrDefault(p => p.Name.Equals(blockName, StringComparison.OrdinalIgnoreCase))
.GetValue(obj, null).ToString();
}
}), RegexOptions.Multiline);
}
}
它的工作,但我正在尋找辦法,使之更加有效。我不知道這是否是正確的實施方式?
謝謝。
嘗試從控制檯應用程序執行時,這會變得很糟糕 – Shawn 2011-02-10 21:27:45