ome/img/nav3_on.png">
APP
系统平台
  • 建站知识
  • 联系我们
  • 咨询热线 :
    028-86922220

    疆括仕网站建设,新征程启航

    为企业提供网站建设、域名注册、服务器等服务

    使用Spring.Net怎么在MVC中实现注入

    本篇文章为大家展示了使用Spring.Net怎么在MVC中实现注入,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

    创新互联于2013年成立,是专业互联网技术服务公司,拥有项目网站建设、成都做网站网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元边坝做网站,已为上家服务,为边坝各地企业和个人服务,联系电话:18980820575

    情景

    public class HomeController : Controller
      {
        //这是一个很神奇的注入
        private IBLL.IUserInfoService UserInfoService { get; set; }
        public ActionResult Index()
        {
          return Content(UserInfoService.GetName());
        }
      }

    每次看代码都有不一样的理解,今天我在看MVC控制器中一个通过Spring.Net依赖注入的UserInfoService属性时,突然有些疑问,注入的前提是控制反转,这么说我的Controller是从IoC容器中来的了?但是我不记得在哪个地方有配置额,对此我展开了深入的研究。

    从MVC本身开始

    首先我们要搞懂MVC本身是通过什么方式获取控制器对象的,本质如果都没有搞懂,又何来扩展呢?

    在MVC模式下,通过实现IControllerFactory接口的对象来获取当前请求的控制器对象,实现IControllerFactory接口的对象也就是控制器的创建工厂。

    简单看下IControllerFactory

    //
      // 摘要:
      //   定义控制器工厂所需的方法。
      public interface IControllerFactory
      {
        //
        // 摘要:
        //   使用指定的请求上下文来创建指定的控制器。
        //
        // 参数:
        //  requestContext:
        //   请求上下文。
        //
        //  controllerName:
        //   控制器的名称。
        //
        // 返回结果:
        //   控制器。
        IController CreateController(RequestContext requestContext, string controllerName);
        //
        // 摘要:
        //   获取控制器的会话行为。
        //
        // 参数:
        //  requestContext:
        //   请求上下文。
        //
        //  controllerName:
        //   你想要获取器其会话行为的控制器的名称。
        //
        // 返回结果:
        //   控制器的会话行为。
        SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName);
        //
        // 摘要:
        //   释放指定的控制器。
        //
        // 参数:
        //  controller:
        //   控制器。
        void ReleaseController(IController controller);
      }

    一个Http请求过来,选择哪个控制器是通过MvcHandler来处理的

    控制器工厂是通过ControllerBuilder的Current属性提供给MvcHandler使用的

    下面的代码是反编译过来的,简单看下即可(因为我要标记黄色高亮部分,所以没有折叠)

    internal ControllerBuilder ControllerBuilder
    {
      get
      {
        if (this._controllerBuilder == null)
        {
          this._controllerBuilder = ControllerBuilder.Current;
        }
        return this._controllerBuilder;
      }
      set
      {
        this._controllerBuilder = value;
      }
    }
    public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
    {
      // Fields
      private ControllerBuilder _controllerBuilder;
      private static readonly object _processRequestTag;
      internal static readonly string MvcVersion;
      public static readonly string MvcVersionHeaderName;
    
      // Methods
      static MvcHandler();
      public MvcHandler(RequestContext requestContext);
      protected internal virtual void AddVersionHeader(HttpContextBase httpContext);
      protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state);
      protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state);
      protected internal virtual void EndProcessRequest(IAsyncResult asyncResult);
      private static string GetMvcVersionString();
      protected virtual void ProcessRequest(HttpContext httpContext);
      protected internal virtual void ProcessRequest(HttpContextBase httpContext);
      private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory);
      private void RemoveOptionalRoutingParameters();
      IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData);
      void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result);
      void IHttpHandler.ProcessRequest(HttpContext httpContext);
    
      // Properties
      internal ControllerBuilder ControllerBuilder { get; set; }
      public static bool DisableMvcResponseHeader { get; [CompilerGenerated] set; }
      protected virtual bool IsReusable { get; }
      public RequestContext RequestContext { get; [CompilerGenerated] private set; }
      bool IHttpHandler.IsReusable { get; }
    
      // Nested Types
      [Serializable, CompilerGenerated]
      private sealed class <>c
      {
        // Fields
        public static readonly MvcHandler.<>c <>9;
        public static BeginInvokeDelegate <>9__20_0;
        public static EndInvokeVoidDelegate <>9__20_1;
        public static Func, bool> <>9__26_0;
    
        // Methods
        static <>c();
        public <>c();
        internal IAsyncResult b__20_0(AsyncCallback asyncCallback, object asyncState, MvcHandler.ProcessRequestState innerState);
        internal void b__20_1(IAsyncResult asyncResult, MvcHandler.ProcessRequestState innerState);
        internal bool b__26_0(KeyValuePair entry);
      }
    
      [StructLayout(LayoutKind.Sequential)]
      private struct ProcessRequestState
      {
        internal IAsyncController AsyncController;
        internal IControllerFactory Factory;
        internal RequestContext RequestContext;
        internal void ReleaseController();
      }
    }

    默认工厂

    默认情况下,在ControllerBuilder内部会创建一个DefaultControllerFactory类型的对象,以提供处理请求。

    DefaultControllerFactory是实现IControllerFactory接口的。

    //
      // 摘要:
      //   表示默认情况下已注册的控制器工厂。
      public class DefaultControllerFactory : IControllerFactory
      {
        //
        // 摘要:
        //   初始化 System.Web.Mvc.DefaultControllerFactory 类的新实例。
        public DefaultControllerFactory();
        //
        // 摘要:
        //   使用控制器激活器来初始化 System.Web.Mvc.DefaultControllerFactory 类的新实例。
        //
        // 参数:
        //  controllerActivator:
        //   实现控制器激活器接口的对象。
        public DefaultControllerFactory(IControllerActivator controllerActivator);
    
        //
        // 摘要:
        //   使用指定的请求上下文来创建指定的控制器。
        //
        // 参数:
        //  requestContext:
        //   HTTP 请求的上下文,其中包括 HTTP 上下文和路由数据。
        //
        //  controllerName:
        //   控制器的名称。
        //
        // 返回结果:
        //   控制器。
        //
        // 异常:
        //  T:System.ArgumentNullException:
        //   requestContext 参数为 null。
        //
        //  T:System.ArgumentException:
        //   controllerName 参数为 null 或为空。
        public virtual IController CreateController(RequestContext requestContext, string controllerName);
        //
        // 摘要:
        //   释放指定的控制器。
        //
        // 参数:
        //  controller:
        //   要释放的控制器。
        public virtual void ReleaseController(IController controller);
        //
        // 摘要:
        //   检索指定请求上下文和控制器类型的控制器实例。
        //
        // 参数:
        //  requestContext:
        //   HTTP 请求的上下文,其中包括 HTTP 上下文和路由数据。
        //
        //  controllerType:
        //   控制器的类型。
        //
        // 返回结果:
        //   控制器实例。
        //
        // 异常:
        //  T:System.Web.HttpException:
        //   controllerType 为 null。
        //
        //  T:System.ArgumentException:
        //   无法分配 controllerType。
        //
        //  T:System.InvalidOperationException:
        //   无法创建 controllerType 的实例。
        protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType);
        //
        // 摘要:
        //   返回控制器的会话行为。
        //
        // 参数:
        //  requestContext:
        //   请求上下文。
        //
        //  controllerType:
        //   控制器的类型。
        //
        // 返回结果:
        //   控制器的会话行为。
        protected internal virtual SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType);
        //
        // 摘要:
        //   检索指定名称和请求上下文的控制器类型。
        //
        // 参数:
        //  requestContext:
        //   HTTP 请求的上下文,其中包括 HTTP 上下文和路由数据。
        //
        //  controllerName:
        //   控制器的名称。
        //
        // 返回结果:
        //   控制器类型。
        protected internal virtual Type GetControllerType(RequestContext requestContext, string controllerName);
      }

    默认情况下,Controller类需要提供默认的构造函数,因为DefaultControllerFactory是通过反射来创建Controller对象实例的。

    如果我们定义的Controller需要通过构造函数创建,或者通过某个IoC容器管理Controller,可以通过自定义控制器工厂来实现。

    自定义控制器工厂

    为什么说这么多关于控制器工厂的东西呢,其实Spring.Net就是通过继承DefaultControllerFactory创建SpringControllerFactory的。

    说了这么多就是为了后面可以更容易的理解Spring.Net的控制器工厂源码罢了。

    回归正题,接着创建自己的控制器工厂。

    1.Home控制器内容如下

    public class HomeController : Controller
      {
        private IUserInfoService UserInfoService { get; set; }
        public HomeController(IUserInfoService userInfoService)
        {
          UserInfoService = userInfoService;
        }
        public ActionResult Index()
        {
          return Content(UserInfoService.GetName());
        }
      }

    这里的UserInfoService只是一个很简陋的测试类,只有一个GetName()方法用来返回“小明”。

    接下来将通过自定义控制器工厂实现构造注入UserInfoService

    2.创建控制器工厂MyControllerFactory

    为了方便我直接继承了DefaultControllerFactory,当然也可以通过实现IControllerFactory来创建

    public class MyControllerFactory : DefaultControllerFactory
      {
        private static readonly IBLL.IUserInfoService userInfoService = new BLL.UserInfoService();
    
        //重写CreateController
        public override IController CreateController(RequestContext requestContext, string controllerName)
        {
          IController controller = null;
          if (controllerName == "Home")
          {
            //如果是我们制定的Home控制器则给其实例化,并通过构造参数注入userInfoService
            controller = new HomeController(userInfoService);
          }
          else
          {
            //通过默认控制器工厂创建控制器
            controller = base.CreateController(requestContext, controllerName);
          }
          return controller;
        }
      }

    3.在Global.asax中注册

    protected void Application_Start()
        {
          MyControllerFactory myControllerFactory = new MyControllerFactory();
          //通过ControllerBuilder设置制定的控制器工厂
          ControllerBuilder.Current.SetControllerFactory(myControllerFactory);
          AreaRegistration.RegisterAllAreas();
          RouteConfig.RegisterRoutes(RouteTable.Routes);
        }

    4.运行测试(神奇不再神奇)

    使用Spring.Net怎么在MVC中实现注入

    意料之外,情理之中,我们并没有在控制器中实例化,结果却出来了

    (实例化在工厂中完成了)

    Spring.Net注入原理

    说了这么多,回头看看标题“Spring.Net是怎么在MVC中实现注入的”,你倒是说啊,等的花都谢了,连Spring.Net的毛都没看到.....

    其实,如果你是认真读过来的,答案在你心中应该已经有了。

    答案如下

    namespace Spring.Web.Mvc
    {
      /// 
      /// Controller Factory for ASP.NET MVC
      /// 
      public class SpringControllerFactory : DefaultControllerFactory
      {
        private static IApplicationContext _context;
    
        /// 
        /// Gets the application context.
        /// 
        /// The application context.
        public static IApplicationContext ApplicationContext
        {
          get
          {
            if (_context == null || _context.Name != ApplicationContextName)
            {
              if (string.IsNullOrEmpty(ApplicationContextName))
              {
                _context = ContextRegistry.GetContext();
              }
              else
              {
                _context = ContextRegistry.GetContext(ApplicationContextName);
              }
            }
    
            return _context;
          }
        }
    
        /// 
        /// Gets or sets the name of the application context.
        /// 
        /// 
        /// Defaults to using the root (default) Application Context.
        /// 
        /// The name of the application context.
        public static string ApplicationContextName { get; set; }
    
        /// 
        /// Creates the specified controller by using the specified request context.
        /// 
        /// The context of the HTTP request, which includes the HTTP context and route data.
        /// The name of the controller.
        /// A reference to the controller.
        /// The  parameter is null.
        /// The  parameter is null or empty.
        public override IController CreateController(RequestContext requestContext, string controllerName)
        {
          IController controller;
    
          if (ApplicationContext.ContainsObjectDefinition(controllerName))
          {
            controller = ApplicationContext.GetObject(controllerName) as IController;
          }
          else
          {
            controller = base.CreateController(requestContext, controllerName);
          }
    
          AddActionInvokerTo(controller);
    
          return controller;
        }
    
        /// 
        /// Retrieves the controller instance for the specified request context and controller type.
        /// 
        /// The context of the HTTP request, which includes the HTTP context and route data.
        /// The type of the controller.
        /// The controller instance.
        /// 
        ///    is null.
        /// 
        ///    cannot be assigned.
        /// An instance of  cannot be created.
        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
          IController controller = null;
    
          if (controllerType != null)
          {
            var controllers = ApplicationContext.GetObjectsOfType(controllerType);
            if (controllers.Count > 0)
            {
              controller = (IController)controllers.First().Value;
            }
          }
    
          if (controller == null)
          {
            //pass to base class for remainder of handling if can't find it in the context
            controller = base.GetControllerInstance(requestContext, controllerType);
          }
          
          AddActionInvokerTo(controller);
    
          return controller;
        }
    
        /// 
        /// Adds the action invoker to the controller instance.
        /// 
        /// The controller.
        protected virtual void AddActionInvokerTo(IController controller)
        {
          if (controller == null)
            return;
    
          if (typeof(Controller).IsAssignableFrom(controller.GetType()))
          {
            ((Controller)controller).ActionInvoker = new SpringActionInvoker(ApplicationContext);
          }
        }
      }
    }

    上述内容就是使用Spring.Net怎么在MVC中实现注入,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注创新互联行业资讯频道。


    网页题目:使用Spring.Net怎么在MVC中实现注入
    网址分享:https://www.tyhkzb.com/article/jiicpc.html
    在线咨询
    服务热线
    服务热线:028-86922220
    TOP