Spring.Net从Java 的Spring 的.Net版本,基本上和Spring差不多的实现。Java社区的速度比.net要快太多,也要成熟太多,.Net社区有太多的东西要从Java社区学习,不过基于.Net的不成熟,也留下了更多的空间,创新的空间也同样存在。希望.Net也能出现Java一样近十年的辉煌,不过对于未来十年,形势很难判断,十年时间,语言,技术,架构,思想,都会有太多的变化。不过现在先踩着前辈们的脚步走一步思考一步了。
   Spirng.Net是一个企业级应用程序框架。里面包括了目前比较流行的一些开发思想:依赖注入(DI,又称为IOC,Martin Fowler有一篇著名的文章里面比较详细的对此作了叙述--Inversion of Control Containers and the Dependency Injection pattern),AOP(面向方面编程)等一些主流架构思想。并且包含一个IOC容器与AOP库。
   下面这个例子是Martin Fowler以及Spring.Net给出的一个例子,比较清楚的阐述了IOC的思想,以及可以对Spring.Net有个大概的了解。
   列出由一位特定导演执导的电影清单。

public class MovieLister…
    
public Movie [] MoviesDirectedBy (string director)
        
{
            IList allMovies 
= _movieFinder.FindAll ();
            IList movies 
= new ArrayList ();
            
foreach (Movie m in allMovies)
            
{
                
if (director.Equals (m.Director))
                
{
                    movies.Add (m);
                }

            }

            
return (Movie []) ArrayList.Adapter (movies).ToArray (typeof (Movie));
        }

    }

这个例子很简单,一个MovieLister类,一个MoviesDirectedBy方法,并返回一个Movie[]数组,这个数组列出指定导演执导的电影清单。MoviesDirectedBy请求_movieFinder(影片搜索者)对象返回后者所知道的所有电影,然后遍历返回的所有电影并返回要求的结果。在这里我们需要考察的是_movieFinder对象,如何将MovieLister对象与特定的_movieFinder对象联接起来是我们关心的问题。因为我们希望这个MoviesDirectedBy方法完全不依赖于电影存储方式。因此这个方法只能引用一个_movieFinder对象,而_movieFinder对象必需对FindAll方法作出反应,在这里我们定义一个接口:

public interface IMovieFinder
    
{
        
/// <summary>Finds all of the stored movies.</summary>
        
/// <returns>All of the stored movies.</returns>

        IList FindAll ();
    }

现在两个对象之间没有耦合关第,但是,如果要找到电影列表,则要涉及到IMovieFinder的某个具体子类。如果我们将“涉及到某个具体子类”的代码实现在MovieLister 的构造函数里,
public class MovieLister
    
{
        
private IMovieFinder _movieFinder;
        
public MovieLister ()
        
{
            _movieFinder 
= new ColonDelimitedMovieFinder("movielist.txt");
        }

这当然是可以的,而且实现起来也没有问题,但是如果我们把电影存储在不同的地方,Excel, Oracle 数据库中,这时我们就需要更改代码才能实现原有的功能。由于我们已经定义了IMovieFinder 类,我们可以不用修改 MoviesDirectedBy方法,但是我们仍需要通过其他途径获得合适的IMovieFinder实现类的实例。在上面的代码中,MovieLister 既依赖于IMovieFinder接口,也依赖于具体的实现类。现在我们需要找到一个方法,让MovieLister只依赖于IMovieFInder接口,而不依赖具体的实现类。这里的问题就是,如何使MovieLister在不知道_movieFinder具体实现类细节的情况下与其实例协同工作。这时候(Inversion of Control)控制反转模式就发挥了作用。
控制反转(依赖注入)
   Movie Finder中的例子:目的是得到IMovieFinder 实现类的实类,Spring.net --Ioc IapplicationContext 容器可以帮我们做到这一点,以下的例子是从配制文件中得到IapplicationContext 实例。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
<configSections>
        
<sectionGroup name="spring">
            
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
            
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
        
</sectionGroup>
    
</configSections>
    
<spring>
        
<context>
            
<resource uri="config://spring/objects"/>
        
</context>
        
<objects xmlns="http://www.springframework.net">
            
<description>An  example that demonstrates simple IoC features.</description>
        
</objects>
    
</spring>
</configuration>

然后用下面的语句得到IapplicationContext的实例

public static void Main ()
    
{
      IApplicationContext ctx 
= ContextRegistry.GetContext();
    }
返回一个在XML文件中用<objects/>标识的完整的实现。如下便在XML中给出的MovieLister的定义,
<objects>
    
<object name="MyMovieLister"
      type
="Spring.Examples.MovieFinder.MovieLister, Spring.Examples.MovieFinder">
    
</object>
</objects>
并且用唯一的命名"MyMovieLister"限定了这个object,然后ctx.GetObject("MyMovieLister")得到这个对象的实现。

    
public static void Main ()
    
{
      IApplicationContext ctx 
= ContextRegistry.GetContext();
      MovieLister lister 
= (MovieLister) ctx.GetObject ("MyMovieLister");
    }

但是lister 实例这个时候没有一个合适的IMovieFinder接口的实现,如果使用MoviesDirectedBy会报出错误。在下面的XML文件中,同样给出了MovieFinder的定义,我们需要将下面这个IMovieFinder的实现注入lister.
<objects>
    
<object name="MyMovieFinder"
        type
="Spring.Examples.MovieFinder.SimpleMovieFinder, Spring.Examples.MovieFinder"/>
    
</object>
</objects>
这个时候就需要某一种方法将其注入到lister中,下面使用了设值的方法进行了依赖注入,
<objects>
    
<object name="MyMovieLister"
      type
="Spring.Examples.MovieFinder.MovieLister, Spring.Examples.MovieFinder">
        
<!-- using setter injection -->
        
<property name="movieFinder" ref="MyMovieFinder"/>
    
</object>
    
<object name="MyMovieFinder"
        type
="Spring.Examples.MovieFinder.SimpleMovieFinder, Spring.Examples.MovieFinder"/>
    
</object>
</objects>
这时候,IMovieFinder的一个实现已经注入给MovieLister,

    
public static void Main ()
    
{
      IApplicationContext ctx 
= ContextRegistry.GetContext();
      MovieLister lister 
= (MovieLister) ctx.GetObject ("MyMovieLister");
      Movie[] movies 
= lister.MoviesDirectedBy("Roberto Benigni");
      Console.WriteLine (
"\nSearching for movie\n");
      
foreach (Movie movie in movies)
      
{
          Console.WriteLine (
              
string.Format ("Movie Title = '{0}', Director = '{1}'.",
              movie.Title, movie.Director));
      }

      Console.WriteLine (
"\nMovieApp Done.\n\n");
    }

我们可以看一下这个时候的关系图,

这个时候我们就可以完整的实现这个方法了,并且MovieLister和MovieFinder解除耦合关系,通过配制我们可以从多个来源得到电影列表。
   当然Spring.Net各IOC所包括的内容远远不止这些,需要我们更深一步的去学习与探究。
Posted on 2006-10-27 17:22  GerryJiang  阅读(1236)  评论(0编辑  收藏  举报