前述:今天主要介绍Ioc以及通过Unit如何实现这种机制。
一、IOC概念的引出
我们都知道在设计分层架构,层与层之间应该是松散耦合,这个可以说是老生常谈的概念。“松散耦合”实际是指上层类不能具体依赖于下层类,而应该依赖于下层提供的一个接口。
所以通常做法是在层与层之间通过接口来对接,来解耦,举个简单的例子:
public interface IIoC
{
void ShowIoc();
}
public class IoC : IIoC
{
public void ShowIoc()
{
//实现逻辑
}
}
static void Main(string[] args)
{
IIoC ioc = new Ioc();
ioc.ShowIoc();
}
上面的代码看着貌似也行,通过接口来调用,也符合OO原则,但是一定程度上还是相对紧耦合.为了实现解耦,GOF模式也就顺理成章的引出.
比如非常经典的抽象工厂模式(Abstact Factory).下面直接上代码.
public class IoCInjector
{
public object GetIoCObject(string className)
{
object iocObj;
string AssemblyName, fullClassName;
AssemblyName= System.Configuration.ConfigurationManager.AppSettings("AssemblyName")
//命名空间+类的名称,指明要实例化的类的路径
fullClassName = AssemblyName+ "." + className
//通过反射,取得数据访问层对象
iocObj = Assembly.Load(AssemblyName).CreateInstance(fullClassName)
return iocObj
}
}
<appSettings>
<add key = "AssemblyName" value = "抽象工厂模式" />
</appSettings>
public interface IAbstractFactory {
public IIoC CreateIoc();
}
public class AbstractFactory : IAbstractFactory {
IoCInjector iocInjector = new IoCInjector();
public IIoC CreateIoC(){
IIoC iioc = iocInjector.GetIoCObject("IoC") as IIoC; //将实例注入,而不需要去new实例化
return iioc;
}
}
public class Client {
public static void main(string[] args){
IAbstractFactory abstractFactory = new AbstractFactory ();
abstractFactory.CreateIoc().ShowIoc();
}
}
看了上面的代码,可以大概了解IOC大概是个什么意思;理论上来说也就是将类之间的关系通过第三方进行注射,不需要类自己去解决调用关系。也就是实现调用者和被调用者解耦.
IOC又称Dependency Injection模式(DI):是依赖注射的意思,也就是将依赖先剥离,然后在适当时候再注射进入。
而通过上面的例子依赖注入的理论基础是Abstract Factory设计模式,那下面就真正引入IoC机制,继续看代码。
public class UnityDependencyResolver{
private readonly IUnityContainer _container;
public UnityDependencyResolver()
: this(new UnityContainer())
{
}
public UnityDependencyResolver(IUnityContainer container)
{
if (container == null)
throw new ArgumentNullException("container");
this._container = container;
//code container
ConfigureContainer(this._container);
}
protected virtual void ConfigureContainer(IUnityContainer container){
container.RegisterType<IIoC, IoC>(); //(c#) code 方式实现
}
protected virtual void ConfigureContainer(IUnityContainer container){ //Config方式实现
UnityConfigurationSection section = ConfiguratinManager.GetSection("Unity") as UnityConfigurationSection;
container.LoadConfiguration(section);
}
public T Resolve<T>(){
T obj = default(T);
if (container.IsRegistered<T>())
obj = container.Resolve<T>();
else throw new Exception("没有 " + name);
return obj;
}
public T Resolve<T>(string name)
{
T obj = default(T);
if (container.IsRegistered<T>(name))
obj = container.Resolve<T>(name);
else throw new Exception("没有 " + name);
return obj;
}
}
public static class IoCC{
private static DependencyResolver _resolver;
public static void InitializeWith(DependencyResolverFactory factory)
{
if (factory == null)
throw new ArgumentNullException("factory");
_resolver = factory.CreateInstance();
}
public static T Resolve<T>()
{
return _resolver.Resolve<T>();
}
public static T Resolve<T>(string name)
{
return _resolver.Resolve<T>(name);
}
}
下面是Config的xml配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<Unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IIoC" type="Unity.IIoC, Unity" />
<alias alias="IoC" type="Unity.IoC, Unity" />
<container>
<register type="IIoC" name="ConfigIIoC" mapTo="IoC" />
</container>
</Unity>
</configuration>
下面是客户端调用,没啥好说的:
public class Cliect{
IIoC iioc = IoCC.Resolve<IoC>(this.GetType().FullName);
iioc.ShowIoc();
}