终于到了题目中的MVC使用StructureMap依赖注入的配置与实现了。在ASP.Net三层架构应用中StructureMap的是最老的IOC/DI工具,也就是依赖注入,很多线上的项目都使用了StructureMap,非常酷的是他是免费的,具体的IOC/DI的设计思想本篇文章不做介绍,想研究可以百度一下,资料很多,哎说道百度想起google一堆泪啊,自从google撤出中国,google是经常的无法访问,很无奈啊很无奈。
依赖注入主要有两种方式:一种是Setter and Getter,一种是构造函数方式。天屹的这套框架使用的后者Constructor构造器的方式。如果你看了前面的文章,就会发现每个Service和Controller中都会有一个构造方法,没错我们就是使用的它们,接下详细的介绍一下StructureMap是怎么在我们的项目中实现依赖注入的。

一.配置与注册Services和Repositories
首先我们告诉StructureMap,我们需要注入的是什么,本系统中需要注册的是Services和Repositories,分别注入到Controller和Service。下面是具体写法,为什么这么写,不必较真,写法是StructureMap提供给我们的,使用就好了。
-
using
System
;
-
using
System.Collections.Generic
;
-
using
System.Linq
;
-
using
System.Text
;
-
using
System.Threading.Tasks
;
-
using
StructureMap
;
-
-
namespace TYStudioDemo.
StructureMap
-
{
-
public
class BootStrapper
-
{
-
public
static
void ConfigureStructureMap()
-
{
-
ObjectFactory.
Configure(x
=>
-
{
-
x.
AddRegistry(
new TYStudioDemoStructureMapRegistry())
;
-
-
x.
Scan(scanner
=>
-
{
-
scanner.
Assembly(
"TYStudioDemo.Services")
;
-
scanner.
Assembly(
"TYStudioDemo.Repositories")
;
-
})
;
-
})
;
-
}
-
}
-
}
上面的代码告诉了StructureMap去哪里找我们的Service和Repositories。同时TYStudioDemoStructureMapRegistry这个类告诉了StructureMap该用哪个类去实例化我们的接口,下面是TYStudioDemoStructureMapRegistry的代码:
-
using
System
;
-
using
System.Collections.Generic
;
-
using
System.Linq
;
-
using
System.Text
;
-
using
System.Data
;
-
using
StructureMap.Configuration.DSL
;
-
using
TYStudioDemo.Models
;
-
using
TYStudioDemo.DTO
;
-
using
TYStudioDemo.Interfaces
;
-
using
TYStudioDemo.Services
;
-
using
TYStudioDemo.Repositories
;
-
-
namespace TYStudioDemo.
StructureMap
-
{
-
public
class TYStudioDemoStructureMapRegistry
: Registry
-
{
-
//注册接口实际使用的实现类
-
public TYStudioDemoStructureMapRegistry()
-
{
-
SelectConstructor
<TYEntities
>(()
=>
new TYEntities())
;
-
-
//Exception Handle
-
For
<ITYExceptionService
>().
Use
<TYExceptionService
>()
;
-
-
//Services
-
For(
typeof(ISupplierService)).
Use(
typeof(SupplierService))
;
-
-
//Repositories
-
For(
typeof(ISupplierRepository
<>)).
Use(
typeof(SupplierRepository))
;
-
For(
typeof(IProductRepository
<>)).
Use(
typeof(ProductRepository))
;
-
}
-
}
-
}
现在我们已经配置了StructureMap并且注册了Service和Repository,接下来该告诉系统去使用StructureMap去实例化我们的Controller。
二.创建Controller Factory
既然使用了依赖注入,Controller的实例化当然不能再用系统本身的了,所以我们需要创建一个ControllerFactory:TYStudioDemoStructureMapControllerFactory。
-
using
System
;
-
using
System.Collections.Generic
;
-
using
System.Linq
;
-
using
System.Text
;
-
using
System.Threading.Tasks
;
-
using
System.Web.Mvc
;
-
using
StructureMap
;
-
-
namespace TYStudioDemo.
StructureMap
-
{
-
public
class TYStudioDemoStructureMapControllerFactory
: DefaultControllerFactory
-
{
-
protected
override IController GetControllerInstance(System.
Web.
Routing.
RequestContext requestContext, System.
Type controllerType)
-
{
-
if (controllerType
!=
null)
-
{
-
Controller c
= ObjectFactory.
GetInstance(controllerType)
as Controller
;
-
-
//当返回一个错误页面,View一级异常会被触发
-
c.
ActionInvoker
=
new ErrorHandlingActionInvoker(
new HandleErrorAttribute())
;
-
return c
;
-
}
-
else
-
return null
;
-
}
-
}
-
}
TYStudioDemoStructureMapControllerFactory继承自DefaultControllerFactory,DefaultControllerFactory是MVC默认的Controller Factory,然后重新器获得Controller实例的方法,由StructureMap的ObjectFactory来创建实例,StructureMap会帮我们把Controller构造函数中的参数实例化。
上面的ErrorHandlingActionInvoker方法:
-
using
System
;
-
using
System.Collections.Generic
;
-
using
System.Linq
;
-
using
System.Text
;
-
using
System.Web.Mvc
;
-
-
namespace TYStudioDemo.
StructureMap
-
{
-
public
class ErrorHandlingActionInvoker
: ControllerActionInvoker
-
{
-
private
readonly IExceptionFilter filter
;
-
-
public ErrorHandlingActionInvoker(IExceptionFilter filter)
-
{
-
if (filter
==
null)
-
throw
new ArgumentNullException(
"Exception filter is missing")
;
-
-
this.
filter
= filter
;
-
}
-
-
protected
override FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
-
{
-
var filterInfo
=
base.
GetFilters(controllerContext, actionDescriptor)
;
-
filterInfo.
ExceptionFilters.
Add(
this.
filter)
;
-
return filterInfo
;
-
}
-
}
-
}
Controller Factory创建ok。但是这样系统是不会使用我们自己的Controller Factory的,所以需要通知一下MVC系统。
三.配置Global.asax文件
在Application_Start()方法中也就是项目启动的时候注册StructureMap并通知系统使用我们自己的Controller Factory进行实例化Controller。
-
using
System
;
-
using
System.Collections.Generic
;
-
using
System.Linq
;
-
using
System.Web
;
-
using
System.Web.Http
;
-
using
System.Web.Mvc
;
-
using
System.Web.Optimization
;
-
using
System.Web.Routing
;
-
using
TYStudioDemo.StructureMap
;
-
-
namespace TYStudioDemo.
WebUI
-
{
-
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
-
// visit http://go.microsoft.com/?LinkId=9394801
-
-
public
class MvcApplication
: System.
Web.
HttpApplication
-
{
-
protected
void Application_Start()
-
{
-
AreaRegistration.
RegisterAllAreas()
;
-
-
WebApiConfig.
Register(GlobalConfiguration.
Configuration)
;
-
FilterConfig.
RegisterGlobalFilters(GlobalFilters.
Filters)
;
-
RouteConfig.
RegisterRoutes(RouteTable.
Routes)
;
-
BundleConfig.
RegisterBundles(BundleTable.
Bundles)
;
-
AuthConfig.
RegisterAuth()
;
-
-
//注册StructureMap
-
BootStrapper.
ConfigureStructureMap()
;
-
-
//通过StructureMap返回Controller实例,通过构造器注入
-
ControllerBuilder.
Current.
SetControllerFactory(
new TYStudioDemoStructureMapControllerFactory())
;
-
}
-
-
protected
void Application_EndRequest(
object sender, EventArgs e)
-
{
-
TYStudioDemo.
Models.
TYEntities.
Cleanup()
;
-
}
-
}
-
}
ok,到此StructureMap的配置就全部完成了,接下来我们该怎么使用它呢。
文章开头已经告诉大家了我们使用Constructor构造器的方式进行依赖注入。
四.Controller的写法
既然是构造器就要写构造函数了,见下面写法:
-
ISupplierService _supplierService
;
-
-
public SupplierController(ITYExceptionService tyExceptionService,
-
ISupplierService supplierService)
-
{
-
_tyExceptionService
= tyExceptionService
;
-
_supplierService
= supplierService
;
-
-
}
在构造方法中加入我们要注入的Service接口,然后StructureMap就会根据上面TYStudioDemoStructureMapRegistry的配置去创建我们需要实例化的service对象了。
同样向Service中注入Repository的写法是一样的:
-
ISupplierRepository
<Supplier
> _supplierRepository
;
-
IProductRepository
<Product
> _productRepository
;
-
-
public SupplierService(ISupplierRepository
<Supplier
> supplierRepotitory,
-
IProductRepository
<Product
> productRepository)
-
{
-
_supplierRepository
= supplierRepotitory
;
-
_productRepository
= productRepository
;
-
}
至此StructureMap配置与使用就全部完成了。
总结:
我们发现,我们的参数都是接口类型了,这样的好处就是将来对ISupplierService的实现不一样了,我们只需要重写写一个ISupplierService的实现了,并修改TYStudioDemoStructureMapRegistry使ISupplierService使用新的实现类,就可以了。因为我们使用的都是接口所以方法和参数都是固定的,所以呢~~ Controller中不用修改任何代码,同理Service也是一样的。这样就充分的降低了代码之间的耦合度。
下篇文章将介绍使用Enterprise Library 5.0 实现异常与日志的处理。
转自:http://www.tystudio.net/2013/04/06/mvc-structuremap-config/