Asp.net MVC示例项目“Suteki.Shop”分析之IOC(控制反转)

在Suteki.Shop中,未使用微软自已的Unity框架来实现IOC,而是使用了大名鼎鼎Castle Windsor。

因为引用了Windsor,就有必要简要介绍一下。而我的理解,这个IOC容器(Container)包括下 面几个重要概念:

容器(Container):Windsor是一个反转控制容器。它创建在一个微内核的基 础之上,这个微内核能够扫描类并且试图找到这些类用到哪些对象引用、对象依赖,然后把这些依赖信 息提供给类使用。

组件(Component):也就是我们通常所说的业务逻辑单元及相应的功能实现 ,组件是一个可复用的代码单元。它应该实现并暴露为一个服务。组件是实现一个服务或接口的类。

服务(Service) :也就是相应的组件接口或N个Component按业务逻辑组合而成的业务逻辑接口 。

接口是服务的规范,它创建一个抽象层,你可以轻松的替换服务的实现。

扩张单元插 件(Facilities):提供(可扩张)容器以管理组件。

我们可以直接使用组件(会在下 面的内容中提到),也可以把组件转换成相应的服务接口来使用。

还记得上一篇文章中提到的 Service吗? 说白了,它就是一个服务。而Suteki.Shop做的更“夸张”,只要是带有业务逻 辑性质的功能代码都可以被视为Component或服务,比如说前几篇文章中所提到的Filter,ModelBinder。 甚至是服务组件初始化的辅助类(WindsorServiceLocator)也一并拿下。

为了便于理解,下面 就到Suteki.Shop中看一下其是如何做的:)

首先我们看一下整个Suteki.Shop项目启动的入口,同 时这也是Windsor IOC容器初始化的起点。而这块功能代码是放在了Global.asax (Suteki.Shop\Global.asax)中的Application_Start方法中实现的,下面是该方法的声明:

protected void Application_Start(object sender, EventArgs e)
{
RouteManager.RegisterRoutes(RouteTable.Routes);
InitializeWindsor();
}

代码中的RouteManager.RegisterRoutes是实现对Route规则的绑定,而规则的内容是被 硬编码到RouteManager中实现的。关于Route的资料网上有不少,园子里也有不少朋友写过,这里就不做 说明了。

接就上面方法就会运行InitializeWindsor(),这就是Windsor容器初始化的方法:

/// <summary>
/// This web application uses the Castle Project's IoC container, Windsor see:
/// http://www.castleproject.org/container/index.html
/// </summary>
protected virtual void InitializeWindsor()
{
if (container == null)
{
// create a new Windsor Container
container = ContainerBuilder.Build ("Configuration\\Windsor.config");

WcfConfiguration.ConfigureContainer(container);

ServiceLocator.SetLocatorProvider(() => container.Resolve<IServiceLocator> ());
// set the controller factory to the Windsor controller factory (in MVC Contrib)
System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(container));
}
}

注: “Configuration\\Windsor.config”中的内容较长,主要是一些XML配置节点。大家可以抽 时间阅读一下即可。

这个方法是今天讲解的主要内容,下面就介绍一下其中的代码。

首 先是判断container(IWindsorContainer类型)是否为空,如果容器为空则创建并初始化该容器。也就 是调用ContainerBuilder(Suteki.Shop\ContainerBuilder)类的Build方法来从外部的config文件中加 载默认信息。我们这里就看一下Build方法的实现:

public static IWindsorContainer Build(string configPath)
{
var container = new WindsorContainer(new XmlInterpreter(configPath));

// register handler selectors
container.Kernel.AddHandlerSelector(new UrlBasedComponentSelector(
typeof (IBaseControllerService),
typeof(IImageFileService),
typeof (IConnectionStringProvider)
));

// automatically register controllers
container.Register(AllTypes
.Of<Controller>()
.FromAssembly (Assembly.GetExecutingAssembly())
.Configure(c => c.LifeStyle.Transient.Named (c.Implementation.Name.ToLower())));

container.Register(
Component.For<IUnitOfWorkManager> ().ImplementedBy<LinqToSqlUnitOfWorkManager>().LifeStyle.Transient,
Component.For<IFormsAuthentication> ().ImplementedBy<FormsAuthenticationWrapper>(),
Component.For<IServiceLocator>().Instance(new WindsorServiceLocator(container)),
Component.For<AuthenticateFilter>().LifeStyle.Transient,
Component.For<UnitOfWorkFilter>().LifeStyle.Transient,
Component.For<DataBinder>().LifeStyle.Transient,
Component.For<LoadUsingFilter>().LifeStyle.Transient,
Component.For<CurrentBasketBinder>().LifeStyle.Transient,
Component.For<ProductBinder>().LifeStyle.Transient,
Component.For<OrderBinder>().LifeStyle.Transient,
Component.For<IOrderSearchService>().ImplementedBy<OrderSearchService> ().LifeStyle.Transient,
Component.For<IEmailBuilder> ().ImplementedBy<EmailBuilder>().LifeStyle.Singleton
);

return container;
}

时间: 2024-07-30 13:05:06

Asp.net MVC示例项目“Suteki.Shop”分析之IOC(控制反转)的相关文章

Asp.net MVC示例项目“Suteki.Shop”分析之结束篇

到今天,这个系列的文章就要先告一段落了.其中我用了10篇文章也没有穷尽该项目的设计思想,只 能从中捡了一些我感兴趣的东西进行了分析和说明,正所谓兴趣是最大的动力.当然限于本人水平有限 ,难免有一些认识上的错误,也希望大家在回复中与我进行交流. 下面把一些还未穷尽的内容做一下罗列,以备感兴趣的朋友继续品味. 1.项目中使用了"Rhino.Mocks",有对单元测试和这个项目感兴趣的朋友可以通过测试 代码研究一下. 2.在下面三个文件夹下有大量的辅助类和扩展方法,其中有些代码大家可以很容易

Asp.net MVC示例项目“Suteki.Shop”分析之安装篇

作为这个系列的开篇,本系统会将我在研究这个项目源码中的一些思考和心得介绍给大家. 当然本系统决不是那种所谓的"最佳示范",里面所提到的使用技巧或设计思路只是给大家 在实际工作中提供一个参考,所谓"最好"之类的词汇都是"矬子里拔将军", 相信大家在成功的分析了几个MVC示例之后,会找到适合自己所在团队或公司使用的方式或思路的. 其 实在找一个合适的MVC示例上我已花费了"一些"时间,而这个例子对于我来说,还是相对不 错的(除了文

Asp.net MVC示例项目“Suteki.Shop”分析之ViewData

使用强类型的ViewData好处有许多,比如说在IDE中就会有更好的支持,比如代码提示.同时在View 与Controller之间有更严谨的"约定".在Suteki.Shop项目中作者对强类型的ViewPage引入 是通过MvcContrib实现的,下面就是其ViewPage<T>代码(Suteki.Shop\Views\ViewPage.cs): public class ViewPage<T> : MvcContrib.FluentHtml.ModelVie

Asp.net MVC示例项目“Suteki.Shop”分析之NVelocity模版引擎

在Suteki.Shop中使用了NVeloctiy模版引擎,用于提供可订制的邮件模版.而邮件的功能就是当定单 状态发生变化时,系统会向买家发送邮件通知.其中的邮件信息内容就是采用NVeloctiy的模版(.vm扩 展名)进行订制的. 因为在Sutekie.Shop的最新源码包中只是部分实现了其功能,而全部的功能 还在完善中,所以要运行本文中所说的功能,需要在下面的链接地址中下载其最新程序文件(包括单元 测试文件): http://code.google.com/p/sutekishop/sour

Asp.net MVC示例项目“Suteki.Shop”分析之NHibernate

在Suteki.Shop中内置了提供了基于NHibernate方式的ORM功能,只不过就目前的项目进度还未全部完 成其设计时的构想,另外在单元测试上也没有完整的测试.不过其设计思路还是很有意思的. 就 其将NHibernate引入到项目中的实现方式而言,与Rhino.Commons中所提倡的方式如出一辙,那就是基于 IRepository模式.关于IRepository这个接口的定义在之前的这篇文章中已提到并做了相应说明,所以 这里就不多做解释了. 好了,下面就开始今天的正文. 首先让我们看一下

Asp.net MVC示例项目“Suteki.Shop”分析之Filter

在Suteki.Shop中对于Filter的使用上提供了两种方式,一种是从FilterAttribute(抽象类属性)以及 接口 IActionFilter和 IResultFilter中继承并实现.另一种是我们经常提到的从 ActionFilterAttribute 上继承方式来实现自己的ActionFilter.首先看一下第一种,同时它也是该项 目中被Action广泛使用的方式, 下面是类图: 当然图中最核心的 当属FilterUsingAttribute,它同时继承了 FilterAttr

Asp.net MVC示例项目“Suteki.Shop”分析之数据验证

在Suteki.Shop,实现了自己的数据校验机制,可以说其设计思路还是很有借鉴价值的.而使用这种 机制也很容易在Model中对相应的实体对象(属性)添加校验操作方法.下面就来介绍一下其实现方式. 首先,看一下这样类图: 在Suteki.Shop定 义一个"IValidatingBinder"接口,其派生自IModelBinder: 其接口中定义了一个 重载方法UpdateFrom,其要实现的功能与MVC中UpdateFrom一样,就是自动读取我们在form中定义的有些 元素及其中所包

Asp.net MVC示例项目“Suteki.Shop”分析之Model和Service

在Suteki.Shop中Model的原型是基于Linq to SQL创建的,其dbml文件位于Suteki.Shop\Shop.dbml. 而Suteki.Shop在此文件的基本上,以"partial class "的方式在Suteki.Shop\Model文件夹下 创建了相应的类文件以扩展Shop.dbml中Model类的一些方法和属性声明,如下图: 为了便于 大家理解,下面以Model中的Product.cs为例进行说明. Product是对网站中所销售商品的数据信 息类.在其中

Asp.net MVC示例项目“Suteki.Shop”分析之ModelBinder

在Suteki.Shop中,作者构造了一个ModelBinder基类"DataBinder",其本身继承自 IModelBinder接口,并以此其类派生出其它一些子类类如ProductBinder等等.可以说除了极个别的地方 之外,DataBinder被用于了Suteki.Shop大多数的ModelBinder绑定场景之路. 首先看一下其类图 结构: 作为基类, DataBinder(图中左下方)实现了将HTTP请求过来的数据转换成为模型中相应的类型.其核心方法就是 BindModel