[转载]CMS系统模版引擎设计(3):Label基类的设计 – 氣如蘭兮長不改,心若蘭兮終不移。 – 博客园.
/// Label基类
/// </summary>
public class Label
{
/// <summary>
/// ID,一般用于缓存的Key
/// </summary>
public string ID { get; set; }
/// <summary>
/// 原始的HTML代码
/// </summary>
public string Html { get; set; }
/// <summary>
/// 标签的参数
/// </summary>
public IDictionary<string,Parameter> Parameters { get; set; }
/// <summary>
/// 标签的字段
/// </summary>
public IDictionary<string, Field> Fields { get; set; }
/// <summary>
/// 缓存
/// </summary>
public Cache Cache { get; set; }
/// <summary>
/// 获取需要呈现的HTML
/// </summary>
/// <returns></returns>
public virtual string GetRenderHtml()
{
return string.Empty;
}
}
{
/// <summary>
/// 匹配Label的正则
/// </summary>
private static readonly Regex LabelRegex = new Regex(@”{((?<a>\w+):(?<c>\w+))(?<p>[^}]*)((/})|(}(?<t>(?>(?<o>{\1[^}]*})|(?<-o>{/\1})|(?:(?!{/?\1)[\s\S]))*)(?(o)(?!)){/\1}))“);
/// <summary>
/// 根据模版获取其包含的所有Label
/// </summary>
/// <param name=”template”>模版</param>
/// <param name=”preInit”>Label初始化前需要的工作</param>
/// <returns></returns>
public static IList<Label> Find(string template, Action<Label> preInit)
{
var ms = LabelRegex.Matches(template);
if (ms.Count == 0) return null;
var list = new List<Label>();
foreach (Match m in ms)
{
var label = Create(m.Groups[0].Value, m.Groups[“a“].Value, m.Groups[“c“].Value, m.Groups[“p“].Value, m.Groups[“t“].Value);
//订阅事件
if (preInit != null)
{
label.PreInit += preInit;
}
//查找Label的子Label,如果存在则会替换Label的TemplateString
var labels = Find(label.TemplateString);
if (labels != null)
{
label.TemplateString = label.TemplateString.Replace(labels[0].TemplateString, string.Empty);
}
//label.Init();
list.Add(label);
if (labels != null)
list.AddRange(labels);
}
return list;
}
/// <summary>
/// 重载上面的Find,一般情况下使用该方法,除非需要特殊处理某些标签
/// </summary>
/// <param name=”template”></param>
/// <returns></returns>
public static IList<Label> Find(string template)
{
return Find(template, null);
}
/// <summary>
/// 反射创建一个Label
/// </summary>
/// <param name=”template”>标签的原始HTML,用于替换使用</param>
/// <param name=”a”>程序集名称</param>
/// <param name=”c”>标签类名称</param>
/// <param name=”p”>标签参数</param>
/// <param name=”t”>标签的模版</param>
/// <returns></returns>
private static Label Create(string template, string a, string c, string p, string t)
{
var assembly = Assembly.Load(a);
var label = assembly.CreateInstance(c, true) as Label;
label.Html = template;
label.TemplateString = t;
label.ParameterString = p;
return label;
}
}
细 心的朋友会发现Label又增加了些新内容,是的,这是在设计过程中的填充和修改。没有人一开始就考虑的十分周全,这是一个正常的设计过程。看看 Label的改动,增加了几个属性,一个preinit事件,和一个初始化方法init给定一段html代码,里面会包含若干个label,所以find 会返回一个list,另外我们还需要一个Create方法类反射每一个label。
为什么设计了一个事件?
因为Include标签是需要传参给里面的label的,所以在label初始化之前可能会改动label的parameterString和templateString:) 希望您能理解。
/// 原始的HTML代码
/// </summary>
public string Html { get; set; }
/// <summary>
/// Label的Parameter字符串
/// </summary>
public string ParameterString { get; set; }
/// <summary>
/// Label的模版
/// </summary>
public string TemplateString { get; set; }
/// <summary>
/// 初始化之前的事件
/// </summary>
public event Action<Label> PreInit;
/// <summary>
/// 初始化Label
/// </summary>
public virtual void Init()
{
if (PreInit != null)
{
PreInit(this);
}
//初始化所有参数
Parameters = new ParameterCollection(ParameterString);
//初始化所有字段
Fields = new FieldCollection(TemplateString);
}
好了,写了太久了,大家和我都消化消化,休息下:)后面继续讲Parameters和Fields的设计。