注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

暇隙读书(4)—模式工程化及扩展之二属性注入  

2013-01-24 17:17:58|  分类: UML+设计模式 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

暇隙读书(4)—模式工程化及扩展之二属性注入

之所以拿出属性注入来讲解,主要是这个属性并不是大家在C#中常见的那种属性值的属性。这个指的是Assembler层次上的属性或者说叫特性。

老规矩,还是先看代码:(代码是从书上抄的)

    public interface IAttributedBuilder

    {

        IList<string> Log { get; }      // log build steps

        void BuildPartA();

        void BuildPartB();

        void BuildPartC();

    }

 

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]

    public sealed class DirectorAttribute : Attribute, IComparable<DirectorAttribute>

    {

        public int Priority { get; set; }

        public string MethodName { get; set; }

 

        public DirectorAttribute(int priority, string methodName)

        {

            if (priority <= 0) throw new ArgumentOutOfRangeException("priority");

            if (string.IsNullOrEmpty(methodName))

                throw new ArgumentNullException("methodName");

            Priority = priority;

            MethodName = methodName;

        }

 

        public int CompareTo(DirectorAttribute attribute)

        {

            return attribute.Priority - this.Priority;

        }

    }

 

    public class Director

    {

        public void BuildUp(IAttributedBuilder builder)

        {

            ((DirectorAttribute[])

                builder.GetType().GetCustomAttributes(typeof(DirectorAttribute), false))

            .OrderByDescending(x => x.Priority)

            .ToList<DirectorAttribute>()

            .ForEach(x => InvokeBuildPartMethod(builder, x));

        }

 

        void InvokeBuildPartMethod(

            IAttributedBuilder builder, DirectorAttribute attribute)

        {

            switch (attribute.MethodName)

            {

                case "BuildPartA": builder.BuildPartA(); break;

                case "BuildPartB": builder.BuildPartB(); break;

                case "BuildPartC": builder.BuildPartC(); break;

            }

        }

    }

书上说了,直接继承客户对象和Assembler中的Attribute,会造成深度的耦合,那么就只能使用后者的动态反射方式来实现了。主要是:

        public void BuildUp(IAttributedBuilder builder)

        {

            ((DirectorAttribute[])

                builder.GetType().GetCustomAttributes(typeof(DirectorAttribute), false))

            .OrderByDescending(x => x.Priority)

            .ToList<DirectorAttribute>()

            .ForEach(x => InvokeBuildPartMethod(builder, x));

        }

这里是关键。这个其实是通过反射的方法得到属性中的值。看具体的应用:

    [TestClass]

    public class AttributingFixture

{

//说明:这个是属性Attribute声明的短记法,也就是把习惯的后缀Attribute去掉,如果写成[DirectorAttribut(2,”BuildPartA”)],这就是长记法。因为在前面的属性声明中,AllowMultiple = true

TRUE,所以可以直接声明多个。否则只能使用一个,更具体的用法,大家可去查资料关于属性(或者叫特性)Attribute的用法。

        [Director(3, "BuildPartA")]

        [Director(2, "BuildPartB")]

        [Director(1, "BuildPartC")]

        class AttributedBuilder : IAttributedBuilder

        {

             IList<string> log = new List<string>();

            public IList<string> Log { get { return log; } }

 

            public void BuildPartA() { log.Add("a"); }

            public void BuildPartB() { log.Add("b"); }

            public void BuildPartC() { log.Add("c"); }

        }

 

        [TestMethod]

        public void BuildAccordingToAttribute()

        {

            IAttributedBuilder builder = new AttributedBuilder();

            new Director().BuildUp(builder);

            Assert.AreEqual<string>("a", builder.Log[0]);

            Assert.AreEqual<string>("b", builder.Log[1]);

            Assert.AreEqual<string>("c", builder.Log[2]);

        }

    }

另外一个需要说明的是,上面变红的一行中的类,这个容易和属性的用法弄晕,特别是初学者。多看看书就行了,没啥特别的。

春节,就要到了。学着又来劲了,哈哈。

  评论这张
 
阅读(609)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017