zoukankan      html  css  js  c++  java
  • CMS系统模板引擎设计(4):Parameter类设计

    紧接上回,说到Parameter和Field了。
    在Label初始化的时候,同时也要对ParameterCollection和FiledCollection初始化。在上节有个属性是这样写的ArticleId=Url(articleid),意思是ArticleId 的值是url的query里的articleid的参数的值。而且还有个 DateFormat="yyyy年MM月dd日"。所以可以看出Parameter的多样化,我个人认为Parameter是最难设计的!以至于我现在写博文都心虚,我之前的系统里对Parameter处理的也比较糟糕,有不少hardcode。
    我们说下Parameter的麻烦之处:
    1、我们具体Label(Article的List)需要获取Parameter的值,有int string bool等,所以Parameter需要把本身的value可转成任意基础类型
    2、有的Parameter的value不是具体值,而是一个方法调用,我们需要反射这个方法,这个方法存在哪里?Core还是具体的某个模块(比如文章)实现的
    3、像Format之类的Parameter显然是用来处理“后事”的,他不会用到前期取值,而是得到后的format工作,也就是需要传一个未知的值。
    4、如何做到Label也可以用,Field也可以用。前者主要用做参数,后者主要用来format。当然,前者有时也format。
    带着这几个问题,我们想想Parameter应该有什么样的内容?
        /// <summary>
        /// Label参数类
        /// </summary>
        public class Parameter
        {
            /// <summary>
            /// 参数名
            /// </summary>
            public string Name { get; set; }
            /// <summary>
            /// 参数初始值
            /// </summary>
            public string Value { get; set; }
    
            public Parameter() { }
            public Parameter(string name, string value)
            {
                Name = name;
                Value = value;
            }
            /// <summary>
            /// 获取参数最终值(默认为初始值)
            /// </summary>
            /// <param name="parameters"></param>
            /// <returns></returns>
            public virtual string GetValue(params string[] parameters)
            {
                return Value;
            }
        }
    

    这是Parameter基类,那么Url等特殊的参数我设计成了子类!
        public class Url : Parameter
        {
            public override string GetValue(params string[] parameters)
            {
                return PageCollection.GetCurrentPage().UrlPattern.GetValue(RequestUtility.Rawurl(), Name);
            }
        }
    
        public class Format : Parameter
        {
            public override string GetValue(params string[] parameters)
            {
                if (parameters == null) return string.Empty;
                var val = parameters[0];
                return Value.Replace("@me", val);
            }
        }
    
        public class DateFormat : Parameter
        {
            public override string GetValue(params string[] parameters)
            {
                if (parameters == null) return string.Empty;
                DateTime t;
                if (DateTime.TryParse(parameters[0], out t))
                {
                    return t.ToString(Value);
                }
                return parameters[0];
            }
        }
    

    呵呵,GetValue貌似不是很漂亮,但确实解决了传值不定的情况。那我们如何实例化ParameterCollection的呢?(其实就是看怎么实例化这些Parameter的)
       /// <summary>
        /// Parameter集合
        /// </summary>
        public class ParameterCollection : IEnumerable<Parameter>
        {
            private static readonly Regex FindPattern = new Regex(@"(?<name>\w+)=(?<value>(""([^""]+)"")|('[^']+')|([^\s\}]+))", RegexOptions.Compiled);
    
            private readonly IDictionary<string, Parameter> _dict;
    
            public ParameterCollection(string parameterString)
            {
                //两个return都会造成_dict为null,枚举此类的时候会抛异常,所以把dict实现实例化了
                _dict = new Dictionary<string, Parameter>();
    
                if (parameterString == string.Empty) return;
                var matches = FindPattern.Matches(parameterString);
                if (matches.Count == 0) return;
    
                //开始初始化所有Parameter
                foreach (Match m in matches)
                {
                    var name = m.Groups["name"].Value;
                    var value = m.Groups["value"].Value;
    
                    _dict.AddValue(name, ParameterFactory.Create(name, value));
                }
            }
    
            public Parameter this[string key]
            {
                get { return _dict[key]; }
            }
    
            public IEnumerator<Parameter> GetEnumerator()
            {
                foreach (var item in _dict)
                {
                    yield return item.Value;
                }
            }
    
            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }
    
    其中的AddValue是我写的扩展方法:

            public static void AddValue<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue value)
            {
                if (dict.ContainsKey(key))
                {
                    dict[key] = value;
                }
                else
                {
                    dict.Add(key, value);
                }
            }
    

    代码最会说话,我就不废话了,可以看到这是一个还没完工的Collection,而创建Parameter部分不在这,在Factory 哈哈。
       public static class ParameterFactory
        {
            private static readonly Regex FuncPattern = new Regex(@"(?<func>\w+)\((?<parameter>[^)(]+?)\)", RegexOptions.Compiled);
            /// <summary>
            /// 获取一个Parameter
            /// </summary>
            /// <param name="name"></param>
            /// <param name="value"></param>
            /// <returns></returns>
            public static Parameter Create(string name, string value)
            {
                Parameter parameter;
                if (IsSpecialParameter(name))
                {
                    parameter = GetParameterByName(name);
                }
                else if (FuncPattern.IsMatch(value))
                {
                    parameter = GetParameterByName(name);
                }
                else
                {
                    parameter = new Parameter(name, value);
                }
                return parameter;
            }
            /// <summary>
            /// 是否为特殊名称的Parameter
            /// </summary>
            /// <param name="name"></param>
            /// <returns></returns>
            private static bool IsSpecialParameter(string name)
            {
                return false;
            }
            /// <summary>
            /// 根据参数名获取Parameter(例如format="e.g@me")
            /// </summary>
            /// <param name="name"></param>
            /// <returns></returns>
            private static Parameter GetParameterByName(string name)
            {
                //通过反射创建Parameter类
                return null;
            }
            /// <summary>
            /// 根据参数值获取Parameter(例如"Url(articleid)")
            /// </summary>
            /// <param name="value"></param>
            /// <returns></returns>
            private static Parameter GetParameterByValue(string value)
            {
                return null;
            }
    
        }
    

    方法内部我没写如何实现,无外乎就是反射,所以大家理解思路即可。先判断是否有特殊的name,然后再判断是否有特殊的value,最后再是最普通的。

    这样感觉就灵活的很多,而且如果用户想自定义一些function扩展,自需要在这几的程序集的特定名字空间下实现Parameter的继承,系统会自动find到这个特殊name或value。 不过实际应用中貌似这种需求不是很多,一般系统提供的足够用了。

    写了好几个小时,才刚写好Parameter,后面再说Field的吧,Field还是比较复杂的。

  • 相关阅读:
    linux编程之main()函数启动过程【转】
    dlmalloc(一)【转】
    Linux进程调度原理【转】
    Linux内存管理原理【转】
    malloc原理和内存碎片【转】
    Linux MTD系统剖析【转】
    linux驱动开发:用户空间操作LCD显示简单的图片【转】
    LCD驱动分析【转】
    LCD常用接口原理【转】
    LCD之mipi DSI接口驱动调试流程【转】
  • 原文地址:https://www.cnblogs.com/mad/p/1875290.html
Copyright © 2011-2022 走看看