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还是比较复杂的。

  • 相关阅读:
    volley框架使用
    Insert Interval
    candy(贪心)
    Best Time to Buy and Sell Stock
    Best Time to Buy and Sell Stock III
    distinct subsequences
    edit distance(编辑距离,两个字符串之间相似性的问题)
    trapping rain water
    word break II(单词切分)
    sudoku solver(数独)
  • 原文地址:https://www.cnblogs.com/mad/p/1875290.html
Copyright © 2011-2022 走看看