配置文件+反射确实去除了选择语句的繁琐。带来了优美的赶脚!
首先改进了一下类(接上文):
namespace ClassLib { /// <summary> /// Interface IGreetingStrategy /// </summary> /// <remarks>Editor:v-liuhch CreateTime:2015/6/28 11:01:58</remarks> public interface IGreetingStrategy { string GreetingType { get; } void SetGreetingWords(ITextControl textContrl); } /// <summary> /// Class EnglishGreeting /// </summary> /// <remarks>Editor:v-liuhch CreateTime:2015/6/28 11:02:38</remarks> public class EnglishGreeting : IGreetingStrategy { public string GreetingType { get { return "English"; } } public void SetGreetingWords(ITextControl textContrl) { textContrl.Text = "hello,readers"; } } /// <summary> /// Class ChineseGreeting /// </summary> /// <remarks>Editor:v-liuhch CreateTime:2015/6/28 11:02:56</remarks> public class ChineseGreeting : IGreetingStrategy { private string greetingType; public ChineseGreeting(string greetingType) { this.greetingType = greetingType; } public ChineseGreeting() : this("中文") { } public ChineseGreeting(XmlNode section) { XmlAttribute attr = section.SelectSingleNode("params").Attributes["greetingType"];//获取属性值 greetingType = attr.Value;//为字段赋值 } public string GreetingType { get { return greetingType; } } public void SetGreetingWords(ITextControl textContrl) { textContrl.Text = "你好啊。小读者!"; } } /// <summary> /// Class GeneralClass:这个类可能还有非常多的字段,属性,方法。这里仅仅是简写下 /// PS:GeneralClass是一个普通的类型,这个类内部维护着IGreetingStrategy,调用的时候还是依据多态详细调用。
/// </summary> /// <remarks>Editor:v-liuhch CreateTime:2015/6/28 11:08:04</remarks> public class GeneralClass { private IGreetingStrategy gs; public GeneralClass(IGreetingStrategy gs) { this.gs = gs; } public string GeneralProperty { get { //做一些额外的工作,这里省略 return "<span sytle='color:red'>" + gs.GreetingType + "</span>"; } } public void GeneralMethod(ITextControl textContrl) { //做一些额外的工作,这里省略 gs.SetGreetingWords(textContrl); textContrl.Text = "<span sytle='color:red'>" + textContrl.Text + "</span>"; //省略。。。。
。。。
} } }
然后在配置文件里定义好我们要使用的详细类和自己定义标签的处理程序:
<!--greetingStrategy节点及其处理程序配置--> <configSections> <section name="greetingStrategy" type="ClassLib.GreetingConfigurationHandler,ClassLib"/> </configSections> <greetingStrategy type="ClassLib.ChineseGreeting,ClassLib"> <params greetingType="***中文问候***"/> <!--构造函数的參数--> </greetingStrategy>
这里。ChineseGreeting是我们要使用的类,上面定义的是处理greetingStrategy的类。
接着,写这个类的详细实现:
namespace ClassLib { public class GreetingConfigurationHandler : IConfigurationSectionHandler { /* 处理有參数的构造函数的对象的创建: */ /// <summary> /// 创建配置节处理程序。 /// </summary> /// <param name="parent">父对象。</param> /// <param name="configContext">配置上下文对象。</param> /// <param name="section">节 XML 节点。</param> /// <returns>创建的节处理程序对象。
</returns> /// <exception cref="System.NotImplementedException"></exception> /// <remarks>Editor:v-liuhch CreateTime:2015/6/30 20:34:54</remarks> public object Create(object parent, object configContext, System.Xml.XmlNode section) { //获取节点type属性的值 Type t = Type.GetType(section.Attributes["type"].Value); object obj=null; try { /* 2。在要实例的类中增加一个构造函数,接收一个XmlNode节点,将greeting_stragetgy的节点在此传递,然后在这个构造函数中进行处理;*/ //假设t包括有參数为xmlnode的构造函数,直接使用这个构造函数 Type[] paras = { typeof(XmlNode) }; ConstructorInfo constructors = t.GetConstructor(paras); if (constructors != null) { object[] paramters = { section }; return Activator.CreateInstance(t, paramters); //传入读取到的构造函数的參数 } if (section.SelectSingleNode("params") == null) //无參数构造函数 { obj = Activator.CreateInstance(t); } else //有參数构造函数 { /*1,在此类中对策略类进行处理,取得params节点的属性值,然后传递给详细实例化的类;*/ //获取params节点的属性greetingType的值 XmlAttribute attr = section.SelectSingleNode("params").Attributes["greetingType"]; object[] parameters = { attr.Value }; obj = Activator.CreateInstance(t, parameters); //传入读取到的构造函数的參数 } } catch (Exception) { return null; } return obj ; } } }
在创建方法中,我们先推断ChineseGreeting类有没有一个參数为节点的构造方法。假设有的话。就直接将section当作參数,在利用反射创建类型实例的时候传进去。
假设没有这种构造方法。我们就在这个处理类里面读取XML文件里的參数,然后在类型实例化的时候传进去。
两种方式比較。事实上都是一样的,仅仅过是这个參数读取的早晚的问题;个人对照了下,认为在这个类里面读取配置文件里的构造函数參数的方式更加灵活,个人偏爱。
写个东西測试下:
#region 自己定义节点存储类型信息——反射方法 IGreetingStrategy greetingStrategy = (IGreetingStrategy)ConfigurationManager.GetSection("greetingStrategy"); if (greetingStrategy != null) { GeneralClass generalClass = new GeneralClass(greetingStrategy); ltrGreetingType.Text = generalClass.GeneralProperty; generalClass.GeneralMethod(ltrGreetingWord); } #endregion
嘿嘿,相对方便。
感觉反射强大在把变化抽出来,可是抽出来的这个变化放到哪里去最easy修改或者是后期维护成本较低。于是配置文件这时候就该上了。。。
。
。
。