我正在写一个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