隐藏在.NET中的IoC?

因为最近在看Pico的一些资料,所以对IoC(或者叫Dependency Injection)相关的其他东东也关注了一下。

如果对IoC不熟悉,你可以在今年第三期的《程序员》上面,找到一篇Martin Fowler写的介绍文章。英文原文在这里

在Java平台上,基于IoC的轻量级Container已经不少了,像大家熟悉的SpringPicoContainer(NanoContainer)、Apache Avalon(此Avalon可不是Longhorn里面的那个Avalon)等等,但是.NET平台下除了一个Pico的移植和Spring作者开发Spring.Net的计划外,就少有所见了。

当然有人很不服气,这篇文章的作者认为,IoC根本不是什么新概念,在2000年.NET的测试版里面,就可以看到IoC的影子了。在System.ComponentModel下面,就隐藏着IComponent、IContainer、ISite、IServiceProvider、IServiceContainer等接口和相应的默认实现。

模仿Martin Fowler那篇文章中的代码,我用这些接口和默认实现写了一个IoC的“最小实现”,除了创建了一个新的MyServiceContainer类用来对ServiceContainer做了一下包装之外,其他全部是利用的.Net Framework本身提供的类和接口。

// 创建一个Container
IServiceContainer container = new MyServiceContainer();

// 在Container中注册新的组件
container.AddService(typeof(IMovieFinder), new DefaultMovieFinder());
container.AddService(typeof(IMovieLister), new DefaultMovieLister());


// 也可以从Container中删除组件
//container.RemoveService(typeof(IMovieFinder));

// 从Container中获取指定接口的组件后调用其功能
IMovieLister lister = (IMovieLister) container.GetService(typeof(IMovieLister));
if (lister != null)
{
    lister.ListMovieByName("kaneboy");
}


注意上面代码中,在注册新的组件时,仍然用的HardCode创建新的实例,这里仅作为演示(通常实例类型是放在配置文件中或者完全按照配置文件来自动在Container中创建Component)。

再来看看DefaultMovieFinder的实现:

public class DefaultMovieFinder : System.ComponentModel.Component, IMovieFinder
{
    public String[] FindByName(String name)
    {
        return new String[1] {"Matrix"};
    }
}


DefaultMovieFinder是一个实现了IMovieFinder接口并从System.ComponentModel.Component继承下来的类。

public class DefaultMovieLister : System.ComponentModel.Component, IMovieLister
{
    public void ListMovieByName(String name)
    {
        IMovieFinder finder = (IMovieFinder) this.Site.GetService(typeof(IMovieFinder));
        if (finder != null)
        {
            foreach(String movie in finder.FindByName(name))
            {
                Console.WriteLine(movie);
            }
        }
    }
}


上面是DefaultMovieLister的实现,它是一个实现了IMovieLister并从System.ComponentModel.Component继承下来的类。在ListMovieByName()方法中,它通过Component类自带的Site属性(一个实现了ISite接口的类)来获得了Container中所需的Component。

如果对完整源码感兴趣,可以在这里下载完整的源码项目文件。

原文地址:https://www.cnblogs.com/kaneboy/p/2436774.html