• 交友社区开发_IOC应用


    交友社区开发_IOC应用 2009-12-9

    先来看看现在大型的系统应用,在提及可扩展性上遇到问题点有哪些?

    (1)类之间的依赖;(2)接口依赖;(3)基于配置文件和Reflection的工厂模式; 

     类之间的关系依赖早就不是什么新问题了,做过开发的都知道,这种依赖

    会导致的后果很严重,有不清楚的可以去看看OO的原则。看看如何用IOC方式解决程序集的依赖

    using System;

    namespace test
    {
    public class EnHelloGenerator
    {
    public string GetHelloString(string name)
    {
    return String.Format("Hello, {0}", name);
    }
    }
    }

    SayHello类持有一个对CnHelloGenerator的引用,并负责将生成出来的问候字符串打印出来。

    using System;
    namespace test
    {
    public class SayHello
    {
    private CnHelloGenerator _helloGen;
    public CnHelloGenerator HelloGenerator
    {
    get { return _helloGen; }
    set { _helloGen = value; }
    }
    public void SayHelloTo(string name)
    {
    if(_helloGen != null)
    Console.WriteLine(_helloGen.GetHelloString(name));
    else
    Console.WriteLine("Client.hello is not initialized");
    }
    }
    }

    MainApp.exe负责完成对象的创建、组装以及调用工作:

    using System;
    namespace test
    {
    public class MainApp
    {
    public static void Main()
    {
    SayHello sayHello = new SayHello();
    sayHello.HelloGenerator = new CnHelloGenerator();
    sayHello.SayHelloTo("hello world");
    }
    }
    }
    这里明显可以看到来,不同类间的依赖关系有多强,如果把每个类分布在不同的程序集中,那么程序集包间的依赖!
    有什么办法解决呢,既然类之间的依赖导致耦合过于紧密,按照《设计模式》的理论,我们要依赖于接口。但是人们往往发现,仅仅依赖于接口似乎并不能完全解决问题?
    using System;
    namespace test
    {
    public interface IHelloGenerator
    {
    string GetHelloString(string name);
    }
    public interface ISayHello
    {
    IHelloGenerator HelloGenerator{ get; set; }
    void SayHelloTo(string name);
    }
    public class SayHello : ISayHello
    {
    private IHelloGenerator _helloGen;
    public IHelloGenerator HelloGenerator
    {
    get { return _helloGen; }
    set { _helloGen = value; }
    }
    public void SayHelloTo(string name)
    {
    if(_helloGen != null)
    Console.WriteLine(_helloGen.GetHelloString(name));
    else
    Console.WriteLine("Client.hello is not initialized");
    }
    }
    }
    同样如果把它们分布到不同的程序集中,并没有解决本质问题,当程序集发生变化时,要重新编译。
    那还有什么办法可以解决程序集间的依赖呢?装配,这是一个传统行业的词,把每个程序集看成一个个配件,然后通过工厂把要生产出来的
    产口把需要的组件装配起来。那么只需要一个装配单就够了,就算产口的功能发生了变化,改变了某一个配件的需求,只要修改装配清单就可以了。
    下面这个是以APP为装配清单
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    <configSections>
    <sectionGroup name="test">
    <section name="objects" type="test.ConfigHandler, MainApp" />
    </sectionGroup>
    </configSections>
    <IocInCSharp>
    <objects>
    <object name="SayHello" assembly="SayHello.dll" typeName="test.SayHello">
    <property name="HelloGenerator" assembly="HelloGenerator.dll"
    typeName="test.CnHelloGenerator"></property>
    </object>
    </objects>
    </IocInCSharp>
    using System;
    using System.IO;
    using System.Configuration;
    using System.Reflection;
    namespace test
    {
    public class SayHelloFactory
    {
    public static object Create(string name)
    {
    Assembly assembly;
    object o = null;
    object p;
    string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) +
    Path.DirectorySeparatorChar;
    ConfigInfo cfgInfo = (ConfigInfo)ConfigurationSettings.GetConfig("test/objects");
    //获取到程序集的成员
    ObjectInfo info = cfgInfo.FindByName(name);
    if(info != null)
    {
    assembly = Assembly.LoadFile(rootPath + info.assemblyName);
    o = assembly.CreateInstance(info.typeName);
    Type t = o.GetType();
    for(int i=0; i<info.properties.Count; i++)
    {
    PropertyInfo prop = (PropertyInfo)info.properties[i];

    assembly = Assembly.LoadFile(rootPath + prop.assemblyName);
    p = assembly.CreateInstance(prop.typeName);
    t.InvokeMember(prop.propertyName,
    BindingFlags.DeclaredOnly |
    BindingFlags.Public | BindingFlags.NonPublic |
    BindingFlags.Instance | BindingFlags.SetProperty, null, o, new Object[] {p});
    }
    }
    return o; //返回接口实例
    }
    }
    }
    Assembly.LoadFile()用于将外部文件装载进来;assembly.CreateInstance()根据装载进来的程序集创建一指定类型的对象;t.InvokeMember(prop.propertyName, ........BindingFlags.SetProperty, null, o, new Object[] {p})利用反射机制对创建出来的对象设置属性值。
    using System;
    namespace test
    {
    public class MainApp
    {
    public static void Main()
    {
    ISayHello sayHello = (ISayHello)SayHelloFactory.Create("SayHello");
    //装配清单。
    if(sayHello != null)
    sayHello.SayHelloTo("Hello world");
    else
    Console.WriteLine("Got an Error!");
    }
    }
    }






     
  • 相关阅读:
    IE10 下兼容性问题
    前端面试题十九
    前端面试题十八
    前端面试题十七
    前端面试题十六
    前端面试题十五
    前端面试题十四
    前端面试题十三(兼容)
    前端面试题十二
    前端面试题十一
  • 原文地址:https://www.cnblogs.com/Leung/p/1620578.html
Copyright © 2020-2023  润新知