交友社区开发_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!");
}
}
}






 
原文地址:https://www.cnblogs.com/Leung/p/1620578.html