ASP.NET MVC 的依赖注入

最近留意了一下ASP.NET MVC 的依赖注入,也看了不少相关的文章,自己也尝试了两种,分别为 NInject 和 Unity , 

在使用的过程中,也渐渐的了解了依赖注入的思想,于是从网上下载了一些相关的代码,直接拿来用之,包括来自微软官方的,

也有来自国外牛人博客的,但是使用当中也发生了一些问题,主要问题就是,当客户端请求一个不存在的Controller或者Action的时候

(甚至是请求一个不存在的图片或者资源),会产生异常,网上的大部分代码都会产生错误,这跟使用什么样的DI框架没有关系,

原因就出在覆盖 DefaultControllerFactoryGetControllerInstance 方法的实现上,当遇到不存的Controller 或者 Action 的时候,

抛出的是自定义的异常,而不是 HTTP 异常,于是打开了 MVC 的源码,仔细阅读了 DefaultControllerFactory.GetControllerInstance 的实现,

发现如下代码片断:

复制代码
protected   internal   virtual  IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
    
if  (controllerType  ==   null ) {
        
throw   new  HttpException( 404 ,
            String.Format(
                CultureInfo.CurrentUICulture,
                MvcResources.DefaultControllerFactory_NoControllerFound,
                requestContext.HttpContext.Request.Path));
    }
    
if  ( ! typeof (IController).IsAssignableFrom(controllerType)) {
        
throw   new  ArgumentException(
            String.Format(
                CultureInfo.CurrentUICulture,
                MvcResources.DefaultControllerFactory_TypeDoesNotSubclassControllerBase,
                controllerType),
            
" controllerType " );
    }
    
try  {
        
return  (IController)Activator.CreateInstance(controllerType);
    }
    
catch  (Exception ex) {
        
throw   new  InvalidOperationException(
            String.Format(
                CultureInfo.CurrentUICulture,
                MvcResources.DefaultControllerFactory_ErrorCreatingController,
                controllerType),
            ex);
    }
}
复制代码

 //注意,它抛出的是 Http 404 的异常,就这么点差别,因此经过改良,我也同样的解决了这个问题,下面就是我定义的 ControllerFactory:

 //UnityControllerFactory.cs:  

复制代码
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;
using  System.Web.Mvc;
using  System.Web.Routing;
using  System.Reflection;
using  Microsoft.Practices.Unity;
using  System.Globalization;

///   <summary>
///  依赖注入 ControllerFactory
///   </summary>
///   <remarks>
///  2010-09-18 [Max] 创建。
///   </remarks>
public   class  UnityControllerFactory : DefaultControllerFactory
{
    
///   <summary>
    
///  创建一个 Controller 类实例,覆盖基类方法
    
///   </summary>
    
///   <param name="aRequestContext"> Http请求上下文对象 </param>
    
///   <param name="aControllerType"> Controller类型 </param>
    
///   <returns>
    
///  返回 IController 类实例。
    
///   </returns>
    
///   <remarks>
    
///  2010-10-09 [Max] 创建。
    
///   </remarks>
     protected   override  IController GetControllerInstance(RequestContext aRequestContext, Type aControllerType)
    {
        
// 不适用的方式:
        
// if ( aControllerType == null )
        
// {
        
//     throw new ArgumentNullException( "aControllerType" );
        
// }

        
// if ( !typeof( IController ).IsAssignableFrom( aControllerType ) )
        
// {
        
//     throw new ArgumentException( string.Format( "{0} 不是 Controller。", aControllerType.Name ), "aControllerType" );
        
// }
        
// 适用的方式:
         if  ( aControllerType  ==   null  )
        {
            
throw   new  HttpException(  404 , String.Format( CultureInfo.CurrentUICulture,  " 未发现指定的 Controller {0}。 " , aRequestContext.HttpContext.Request.Path ) );
        }
        
if  (  ! typeof ( IController ).IsAssignableFrom( aControllerType ) )
        {
            
throw   new  ArgumentException( String.Format( CultureInfo.CurrentUICulture,  " {0} 不是 Controller。 " , aControllerType ),  " aControllerType "  );
        }
        
try
        {
            IUnityContainer container  =  GetContainer( aRequestContext );
            
return  (IController) container.Resolve( aControllerType );
        }
        
catch  ( Exception ex )
        {
            
throw   new  InvalidOperationException( String.Format( CultureInfo.CurrentUICulture,  " 无法创建 Controller {0}。 " , aControllerType ), ex );
        }
    }

    
///   <summary>
    
///  获取依赖注入容器对象
    
///   </summary>
    
///   <param name="aContext"> Http请求上下文对象 </param>
    
///   <returns>
    
///  返回 IUnityContainer 类实例。
    
///   </returns>
    
///   <remarks>
    
///  2010-09-18 [Max] 创建。
    
///   </remarks>
     protected   virtual  IUnityContainer GetContainer( RequestContext aContext )
    {
        
if  ( aContext  ==   null  )
        {
            
throw   new  ArgumentNullException(  " aContext "  );
        }

        var unityApp  =  aContext.HttpContext.ApplicationInstance  as  IUnityMvcApplication;
        
if  ( unityApp  ==   null  )
        {
            
throw   new  InvalidOperationException(  " MvcHttpApplication 对象必须从 UnityMvcApplication 继承。 "  );
        }

        IUnityContainer container  =  unityApp.Container;
        
if  ( container  ==   null  )
        {
            
throw   new  InvalidOperationException(  " 依赖注入容器对象无法访问,请查看您的 MvcHttpApplication 类定义是否正确。 "  );
        }
        
return  container;
    }
}
复制代码

 

 

 //IUnityMvcApplication.cs: 

复制代码
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  Microsoft.Practices.Unity;

///   <summary>
///  依赖注入容器访问接口
///   </summary>
///   <remarks>
///  2010-09-18 [Max] 创建。
///   </remarks>
public   interface  IUnityMvcApplication
{
    
///   <summary>
    
///  依赖注入容器属性
    
///   </summary>
    
///   <remarks>
    
///  2010-09-18 [Max] 创建。
    
///   </remarks>
    IUnityContainer Container {  get ; }
}

复制代码

 

 

// 下面这两个单元的代码,由于公司的特殊应用,封装的比较死,不太好,不建议照搬,仅供参考。

//UnityMvcApplication.cs: 

复制代码
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;
using  System.Web.Mvc;
using  System.Web.Routing;
using  System.Reflection;
using  Microsoft.Practices.Unity;

///   <summary>
///  Mvc 应用程序类。
///   </summary>
///   <remarks>
///  2010-09-18 [Max] 创建。
///   </remarks>
public   class  UnityMvcApplication : HttpApplication, IUnityMvcApplication
{

    
private   static  IUnityContainer _UnityContainer;

    
///   <summary>
    
///  静态依赖注入容器属性
    
///   </summary>
    
///   <remarks>
    
///  2010-09-18 [Max] 创建。
    
///   </remarks>
     protected   static  IUnityContainer Container
    {
        
get
        {
            
if  (_UnityContainer  ==   null )
            {
                _UnityContainer  =   new  UnityContainer();
            }
            
return  _UnityContainer;
        }
    }

    
///   <summary>
    
///  实现IMvcApplication接口的依赖注入容器属性
    
///   </summary>
    
///   <remarks>
    
///  2010-09-18 [Max] 创建。
    
///   </remarks>
    IUnityContainer IUnityMvcApplication.Container
    {
        
get
        {
            
return  Container;
        }
    }

    
#region  override methods
    
///   <summary>
    
///  应用程序启动事件
    
///   </summary>
    
///   <remarks>
    
///  2010-09-18 [Max] 创建。
    
///   </remarks>
     protected   virtual   void  Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
        RegisterDependency();
        RegisterControllerFactory();
    }

    
///   <summary>
    
///  应用程序结束事件
    
///   </summary>
    
///   <param name="sender"> 事件发起者 </param>
    
///   <param name="e"> 事件参数 </param>
    
///   <remarks>
    
///  2010-09-18 [Max] 创建。
    
///   </remarks>
     protected   virtual   void  Application_End(  object  sender, EventArgs e )
    {
        CleanUp();
    }
    
#endregion

    
#region  protected virtual methods
    
///   <summary>
    
///  注册全局过滤器
    
///   </summary>
    
///   <param name="aFilters"> 全局过滤器集合 </param>
    
///   <remarks>
    
///  2010-09-18 [Max] 创建。
    
///   </remarks>
     protected   virtual   void  RegisterGlobalFilters(GlobalFilterCollection aFilters)
    {
        aFilters.Add( new  HandleErrorAttribute());
    }

    
///   <summary>
    
///  注册URL路由
    
///   </summary>
    
///   <param name="aRoutes"> 路由器对象 </param>
    
///   <remarks>
    
///  2010-09-18 [Max] 创建。
    
///   </remarks>
     protected   virtual   void  RegisterRoutes(RouteCollection aRoutes)
    {
        aRoutes.IgnoreRoute( " {resource}.axd/{*pathInfo} " );
        aRoutes.MapRoute(
            
" Default " //  Route name
             " {controller}/{action}/{aId} " //  URL with parameters
             new  { controller  =   " Home " , action  =   " Index " , aId  =  UrlParameter.Optional }  //  Parameter defaults
        );
    }

    
///   <summary>
    
///  注册依赖注入对象
    
///   </summary>
    
///   <remarks>
    
///  2010-09-18 [Max] 创建。
    
///   </remarks>
     protected   virtual   void  RegisterDependency()
    {

    }

    
///   <summary>
    
///  注册Controller工厂
    
///   </summary>
    
///   <remarks>
    
///  2010-09-18 [Max] 创建。
    
///   </remarks>
     protected   virtual   void  RegisterControllerFactory()
    {
        ControllerBuilder.Current.SetControllerFactory( typeof (UnityControllerFactory));
    }

    
///   <summary>
    
///  清除资源
    
///   </summary>
    
///   <remarks>
    
///  2010-09-18 [Max] 创建。
    
///   </remarks>
     protected   virtual   void  CleanUp()
    {
        
if  (_UnityContainer  !=   null )
        {
            _UnityContainer.Dispose();
        }
    }
    
#endregion

}
复制代码

 

 

//Global.asax.cs: 

复制代码
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;
using  System.Web.Mvc;
using  System.Web.Routing;
using  System.Reflection;
using  Microsoft.Practices.Unity;

public   class  MvcApplication : UnityMvcApplication
{
    
protected   override   void  Application_Start( )
    {
        
base .Application_Start( );
    }

    
protected   override   void  RegisterDependency( )
    {
        Container.RegisterType < IRDict, DictRepository > ( );
        Container.RegisterType < IRStudent, StudentRepository > ( );
    }
}
复制代码

 

 

//使用 DemoController.cs:  

复制代码
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;
using  System.Web.Mvc;

// using 你的Respository;

using  Microsoft.Practices.Unity;

public   class  DemoController : BaseController
{
    
private  IRDict _dictRepository;
    
private  IRStudent _studentRepository;

    
public  DemoController( IRDict aDictRespository, IRStudent aStudentRespository )
    {
        _dictRepository  =  aDictRespository;
        _studentRepository  =  aStudentRespository;
    }
}
复制代码

  

上面的代码都是从公司封装的框架中提取出来,仅供大家分享。

由于 Unity 已经包含在微软 Enterprise Library 中,因此,只要下载安装Enterprise Library安装包即可。

其实我个人比较喜欢 NInject 又小、又轻便,但由于特殊原因,实在是没有办法,上面这些代码很容易就改成 NInject。

Unity的地址: http://entlib.codeplex.com/

NInject的地址:http://ninject.org/download


转自:http://www.cnblogs.com/cnmaxu/archive/2010/10/12/1848735.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值