終於到了題目中的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/