ASP.NET MVC 3 RTM 更新(2)

三、IResolver<TService>和SingleServiceResolver<TService>:IResolver<TService>、MultiServiceResolver<TService>:IResolver<IEnumerable<TService>>

IResolver<TService>接口只有一个TService型的Current只读属性,返回相应类型的一个对象。这是一个有Lazy意味的轻量接口。
一个简单的IResolver<TService>接口的实现类中,Current可以返回Activator.CreateInstance创建的实例——在面向接口编程方面讲,完全是有意义的。

SingleServiceResolver类是IResolver<TService>的实现,它用于获取单个对象,其实现原理是:在构造对象时,方法内部或作为参数指定一种默认的对象创建(获取)"方式"——方式1,作为参数传入另一种创建(获取)"方式"——方式2和当
当两种创建(获取)对象都不成功的情况下(两种方式都成功,则会抛出异常)提供一个默认对象。

具体来说,在它公共的构造方法中,指定的方式1为DependencyResolver.Current(IDependencyResolver)。
当调用SingleServiceResolver类的Current属性时,首先判断如果方式1不为null,则通过DependencyResolver.Current.GetService(typeof(TService))获取一个TService对象,如果创建(获取)成功,则尝试方式2创建(获取),如果也成功则抛出异常。
返回值的时候,先判方式1如果为null,则获取方式2的执行结果,如果结果不为null,则返回该结果,否则返回默认对象。

在它的internal构造方法中,还允许传入默认创建(获取)方式以赋给方式1。在两个构造方法中还允许传入一个字符串标明是哪个方法在创建SingleServiceResolver对象(或者说Current返回的对象)。在有异常发生时,可以将该字符串传入异常对象。

MultiServiceResolver类也是IResolver<TService>的实现,它用于获取一个集合对象,其实现原理是:在构造对象时,方法内部或作为参数指定一种默认的对象创建(获取)"方式"——方式1,作为参数传入另一种创建(获取)"方式"——方式2。
返回两种方式创建(获取)的集合的合集。

具体来说,在它公共的构造方法中,指定的方式1为DependencyResolver.Current(IDependencyResolver)。
当调用MultiServiceResolver类的Current属性时,首先判断如果方式1不为null,则通过DependencyResolver.Current.GetServices(typeof(TService))获取一个IEnumerable<TService>对象,该集合对象可以没有元素但不能为null,
然后将方式2创建的集合与方式1创建(获取)的集合合并返回。

四、ControllerBuilder

我们知道在MVC2中,Controller通过ControllerFactory创建,而ControllerFactory通过ControllerBuilder的单例ControllerBuilder.Current的GetControllerFactory()方法获取。类的默认构造方法中会初始化一个DefaultControllerFactory对象,并通过SetControllerFactory方法将其包装成一个Func<IControllerFactory>实例,并赋值给_factoryThunk私有委托,当调用GetControllerFactory方法时,返回的是该委托的执行结果。

在MVC3中,ControllerBuilder类的构造方法和GetControllerFactory方法的实现又有所不同。
ControllerBuilder有一个IResolver<IControllerFactory>型的私有变量_serviceResolver。从上面的分析我们知道,IResolver<IControllerFactory>有唯一的只读属性T Current,调用_serviceResolver.Current将返回一个IControllerFactory对象。
默认构造不再直接创建DefaultControllerFactory对象,只是简单的调用新增的接受一个IResolver<IControllerFactory>接口参数的构造方法。该方法目前是internal的。
        internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver) {
            _serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
                () => _factoryThunk(),
                 new DefaultControllerFactory { ControllerBuilder = this },
                "ControllerBuilder.GetControllerFactory"
            );
        }
在有参构造方法内部,如果传入的参数serviceResolver为null则创建一个实现了IResolver<IControllerFactory>接口的SingleServiceResolver<TService>类的对象赋给私有变量_serviceResolver。ControllerBuilder.Current是一个通过默认构造函数创建的对象,用到了单例模式。所以这里serviceResolver参数是为null的。

深入SingleServiceResolver类内部我们知道,它首先会尝试从DependencyResolver.Current.GetService(typeof(IControllerFactory))获取IControllerFactory对象,在默认情况会调用Activator.CreateInstance(typeof(IControllerFactory)),当然会是null。所以最终会创建DefaultControllerFactory作为我们的默认ControllerFactory。

假设定义了一个UnityControllerFactory:IControllerFactory。
首先,我们可以像MVC2中那样使用SetControllerFactory设置IControllerFactory
假设我们又实现了一个UnityDependencyResolver:IDenpendencyResovler,并将其设置为当前的IDenpendencyResovler。
在UnityContainer中将UnityControllerFactory映射到IControllerFactory接口,同样可以达到设置ControllerFactory的目的。

另外,GetControllerFactory方法返回的不再是像MVC2中的_factoryThunk的执行结果,而是_serviceResolver的Current属性。
posted @ 2011-03-25 15:16  alby  阅读(2395)  评论(0编辑  收藏  举报