• 简单剖析Asp.Net MVC 源码中的三个IoC注入点


    注:本文所指MVC框架特指Asp.Net MVC 3.0,文中若有不当之处,请多加包涵,谢谢!

     尊重他人原创,转载请务必注明来自http://www.cnblogs.com/Raoh/archive/2013/03/27/AspNetMvc_IOC.html

    我们在做Asp.Net MVC依赖注入的时候,注入点主要有三个地方,分列如下:
    1.实现了IControllerFactory接口的DefaultControllerFactory;
    2.实现了IDependencyResolver接口的DefaultDependencyResolver;
    3.实现了IControllerActivator接口的DefaultControllerActivator;

    下面,我们简单剖析下这三个注入点的框架源码:
    首先,MVC框架的Controller激活(实例化)过程是由IControllerFactory实现的,
    IControllerFactory的源码如下:

    public interface IControllerFactory {
            IController CreateController(RequestContext requestContext, string controllerName);
            SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName);
            void ReleaseController(IController controller);
    }

    MVC框架中该接口的默认实现是DefaultControllerFactory,由DefaultControllerFactory的GetControllerInstance方法返回一个Controller实例(注意:可以将这里做为第一个依赖注入点),该方法的源码实现如下:

    protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
                if (controllerType == null) {
                    throw new HttpException(404,
                        String.Format(
                            CultureInfo.CurrentCulture,
                            MvcResources.DefaultControllerFactory_NoControllerFound,
                            requestContext.HttpContext.Request.Path));
                }
                if (!typeof(IController).IsAssignableFrom(controllerType)) {
                    throw new ArgumentException(
                        String.Format(
                            CultureInfo.CurrentCulture,
                            MvcResources.DefaultControllerFactory_TypeDoesNotSubclassControllerBase,
                            controllerType),
                        "controllerType");
                }
                return ControllerActivator.Create(requestContext, controllerType);
    }

    跟踪源码,我们会发现,该方法中的ControllerActivator定义如下:

    private IControllerActivator ControllerActivator {
                get {
                    if (_controllerActivator != null) {
                        return _controllerActivator;
                    }
                    _controllerActivator = _activatorResolver.Current;
                    return _controllerActivator;
                }
            }

    跟踪到这里,可以发现该方法的默认实现需要一个IControllerActivator,而其实现指向_activatorResolver.Current,继续跟踪源码,发现_activatorResolver是在DefaultControllerFactory的构造函数中实例化的,其默认指向SingleServiceResolver<IControllerActivator>,其源码如下:

    internal DefaultControllerFactory(IControllerActivator controllerActivator, IResolver<IControllerActivator> activatorResolver, IDependencyResolver dependencyResolver) {
                if (controllerActivator != null) {
                    _controllerActivator = controllerActivator;
                }
                else {
                    _activatorResolver = activatorResolver ?? new SingleServiceResolver<IControllerActivator>(
                        () => null,
                        new DefaultControllerActivator(dependencyResolver),
                        "DefaultControllerFactory contstructor"
                    );
                }
            }

    其中SingleServiceResolver<IControllerActivator>构造函数中的第二个参数,new DefaultControllerActivator(dependencyResolver),就是_activatorResolver.Current,也就是IControllerActivator的默认实现,IControllerActivator的源码如下:

    public interface IControllerActivator {
            IController Create(RequestContext requestContext, Type controllerType);
    }

    该接口仅仅包含一个返回IController的Create方法。(注意:可以将这里做为第二个依赖注入点)

    回头来看看DefaultControllerActivator的源码如下:

    private class DefaultControllerActivator : IControllerActivator {
                Func<IDependencyResolver> _resolverThunk;
    
                public DefaultControllerActivator()
                    : this(null) {
                }
    
                public DefaultControllerActivator(IDependencyResolver resolver) {
                    if (resolver == null) {
                        _resolverThunk = () => DependencyResolver.Current;
                    }
                    else {
                        _resolverThunk = () => resolver;
                    }
                }
    
                public IController Create(RequestContext requestContext, Type controllerType) {
                    try {
                        return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));
                    }
                    catch (Exception ex) {
                        throw new InvalidOperationException(
                            String.Format(
                                CultureInfo.CurrentCulture,
                                MvcResources.DefaultControllerFactory_ErrorCreatingController,
                                controllerType),
                            ex);
                    }
                }
            }

    阅读源码,我们会发现,该方法需要一个IDependencyResolver,IDependencyResolver的源码如下:

    public interface IDependencyResolver {
            object GetService(Type serviceType);
            IEnumerable<object> GetServices(Type serviceType);
    }

    而在DefaultControllerActivator的构造函数中,IDependencyResolver指向DependencyResolver.Current,通过跟踪代码我们会发现DependencyResolver.Current最终指向DefaultDependencyResolver的实例,框架中IDependencyResolver的默认实现就是DefaultDependencyResolver,其源码如下:

    private class DefaultDependencyResolver : IDependencyResolver {
                [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This method might throw exceptions whose type we cannot strongly link against; namely, ActivationException from common service locator")]
                public object GetService(Type serviceType) {
                    try {
                        return Activator.CreateInstance(serviceType);
                    }
                    catch {
                        return null;
                    }
                }
    
                public IEnumerable<object> GetServices(Type serviceType) {
                    return Enumerable.Empty<object>();
                }
            }

    最终由DefaultDependencyResolver的GetService返回一个Controller实例。(注意:可以将这里做为第三个依赖注入点)

    后面有空的话,我会写一些代码示例,简单演示对这三个IoC注入点进行注入。

    注:尊重他人原创,转载请务必注明来自http://www.cnblogs.com/Raoh/archive/2013/03/27/AspNetMvc_IOC.html

  • 相关阅读:
    猜数字游戏,猜三次都不对,则结束游戏,猜一次就成功,结束游戏
    用return关键字实现1——100累加求和,返回总和并接收输出
    用return关键字实现求和操作
    return关键字的作用和接受实验
    数组各元素随机赋值、求和、求平均值、求最大值的各类测试(一维数组)
    日期下拉选择
    22--
    css 17课--
    css盒模型
    css学习
  • 原文地址:https://www.cnblogs.com/Raoh/p/AspNetMvc_IOC.html
Copyright © 2020-2023  润新知