这一篇我们讲解如何利用DependencyResolver来定位我们的自定义服务(service)也就查找Controller.
首先让我们来看一下DependencyResolver 的实现。
DependencyResolver.cs
View Code
1
public
class
DependencyResolver {
2
//
Static accessors
3
4
private
static
DependencyResolver _instance =
new
DependencyResolver();
5
6
public
static
IDependencyResolver Current {
7
get
{
8
return
_instance.InnerCurrent;
9
}
10
}
11
12
public
static
void
SetResolver(IDependencyResolver resolver) {
13
_instance.InnerSetResolver(resolver);
14
}
15
16
public
static
void
SetResolver(
object
commonServiceLocator) {
17
_instance.InnerSetResolver(commonServiceLocator);
18
}
19
20
[SuppressMessage(
"
Microsoft.Design
"
,
"
CA1006:DoNotNestGenericTypesInMemberSignatures
"
, Justification =
"
This is an appropriate nesting of generic types.
"
)]
21
public
static
void
SetResolver(Func<Type,
object
> getService, Func<Type, IEnumerable<
object
>> getServices) {
22
_instance.InnerSetResolver(getService, getServices);
23
}
24
25
//
Instance implementation (for testing purposes)
26
27
private
IDependencyResolver _current =
new
DefaultDependencyResolver();
28
29
public
IDependencyResolver InnerCurrent {
30
get
{
31
return
_current;
32
}
33
}
34
35
private
class
DefaultDependencyResolver : IDependencyResolver {
36
[SuppressMessage(
"
Microsoft.Design
"
,
"
CA1031:DoNotCatchGeneralExceptionTypes
"
, Justification =
"
This method might throw exceptions whose type we cannot strongly link against; namely, ActivationException from common service locator
"
)]
37
public
object
GetService(Type serviceType) {
38
try
{
39
return
Activator.CreateInstance(serviceType);
40
}
41
catch
{
42
return
null
;
43
}
44
}
45
46
public
IEnumerable<
object
> GetServices(Type serviceType) {
47
return
Enumerable.Empty<
object
>();
48
}
49
}
50
}
51
52
DependencyResolver.Current 默认返回的是 DefaultDependencyResolver 类型的实例,在这个类中我们看到它实现了IDependencyResolver.GetService 接口, 这个实现是调用了Activator.CreateInstance(serviceType); 返回一个类型的实例。
这里框架为我们提供了一个时点使我们可以调用DependencyResolver.SetResolver方法来注入我们自己的IDependencyResolver的实现 。
---------------------------------------------------------------------------------------------
接下来我们看MvcHandler,所有的Request请需要在这里查找我们的Controller,在这个类的ProcessRequestInit方法中我们可以看到它调用了 ControllerBuilder.GetControllerFactory(); 先找到Controller的工成类实例IControllerFactory,再调用它的CreateController方法来寻找和创建Controller.
MvcHandler.cs
View Code
1
private
void
ProcessRequestInit(HttpContextBase httpContext,
out
IController controller,
out
IControllerFactory factory) {
2
//
If request validation has already been enabled, make it lazy. This allows attributes like [HttpPost] (which looks
3
//
at Request.Form) to work correctly without triggering full validation.
4
bool
? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(HttpContext.Current);
5
if
(isRequestValidationEnabled ==
true
) {
6
ValidationUtility.EnableDynamicValidation(HttpContext.Current);
7
}
8
9
AddVersionHeader(httpContext);
10
RemoveOptionalRoutingParameters();
11
12
//
Get the controller type
13
string
controllerName = RequestContext.RouteData.GetRequiredString(
"
controller
"
);
14
15
//
Instantiate the controller and call Execute
16
factory = ControllerBuilder.GetControllerFactory();
17
controller = factory.CreateController(RequestContext, controllerName);
18
if
(controller ==
null
) {
19
throw
new
InvalidOperationException(
20
String.Format(
21
CultureInfo.CurrentCulture,
22
MvcResources.ControllerBuilder_FactoryReturnedNull,
23
factory.GetType(),
24
controllerName));
25
}
26
}
-------------------------------------------------------------------------------------------
下面我们看一下ControllerBuilder类,看一下它是如何工作的。
ControllerBuilder.cs
View Code
1
public
class
ControllerBuilder {
2
3
private
Func<IControllerFactory> _factoryThunk = () =>
null
;
4
private
static
ControllerBuilder _instance =
new
ControllerBuilder();
5
private
HashSet<
string
> _namespaces =
new
HashSet<
string
>(StringComparer.OrdinalIgnoreCase);
6
private
IResolver<IControllerFactory> _serviceResolver;
7
8
public
ControllerBuilder()
9
:
this
(
null
) {
10
}
11
12
internal
ControllerBuilder(IResolver<IControllerFactory> serviceResolver) {
13
_serviceResolver = serviceResolver ??
new
SingleServiceResolver<IControllerFactory>(
14
() => _factoryThunk(),
15
new
DefaultControllerFactory { ControllerBuilder =
this
},
16
"
ControllerBuilder.GetControllerFactory
"
17
);
18
}
19
20
public
IControllerFactory GetControllerFactory() {
21
return
_serviceResolver.Current;
22
}
23
}
在构造函数中我们看到它初始化了_serviceResolver 变量,它的类型是SingleServiceResolver<IControllerFactory>,在它初始化时传入了_factoryThunk(返回值为空的委托),和DefaultControllerFactory实例。接下来我们看一下SingleServiceResolver的实现。
SingleServiceResolver.cs
View Code
1
internal
class
SingleServiceResolver<TService> : IResolver<TService>
where
TService :
class
{
2
3
private
TService _currentValueFromResolver;
4
private
Func<TService> _currentValueThunk;
5
private
TService _defaultValue;
6
private
Func<IDependencyResolver> _resolverThunk;
7
private
string
_callerMethodName;
8
9
public
SingleServiceResolver(Func<TService> currentValueThunk, TService defaultValue,
string
callerMethodName) {
10
if
(currentValueThunk ==
null
) {
11
throw
new
ArgumentNullException(
"
currentValueThunk
"
);
12
}
13
if
(defaultValue ==
null
) {
14
throw
new
ArgumentNullException(
"
defaultValue
"
);
15
}
16
17
_resolverThunk = () => DependencyResolver.Current;
18
_currentValueThunk = currentValueThunk;
19
_defaultValue = defaultValue;
20
_callerMethodName = callerMethodName;
21
}
22
23
internal
SingleServiceResolver(Func<TService> staticAccessor, TService defaultValue, IDependencyResolver resolver,
string
callerMethodName)
24
:
this
(staticAccessor, defaultValue, callerMethodName) {
25
if
(resolver !=
null
) {
26
_resolverThunk = () => resolver;
27
}
28
}
29
30
public
TService Current {
31
get
{
32
if
(_resolverThunk !=
null
) {
33
lock
(_currentValueThunk) {
34
if
(_resolverThunk !=
null
) {
35
_currentValueFromResolver = _resolverThunk().GetService<TService>();
36
_resolverThunk =
null
;
37
38
if
(_currentValueFromResolver !=
null
&& _currentValueThunk() !=
null
) {
39
throw
new
InvalidOperationException(String.Format(CultureInfo.CurrentCulture, MvcResources.SingleServiceResolver_CannotRegisterTwoInstances,
typeof
(TService).Name.ToString(), _callerMethodName));
40
}
41
}
42
}
43
}
44
return
_currentValueFromResolver ?? _currentValueThunk() ?? _defaultValue;
45
}
46
}
47
}
我们看到
_resolverThunk = () => DependencyResolver.Current;//这里就为我们注入自己的ControllerFactory提供机会_currentValueFromResolver = _resolverThunk().GetService<TService>();我们知道框架使用了DependencyResolver.Current来提供GetService的功能,如果没有则返回默认的DefaultControllerFactory实例(从构造函数中传入)。
--------------------------------------------------------------------------------------------
接下来我们看DefaultControllerFactory的实现,
View Code
1
public
class
DefaultControllerFactory : IControllerFactory {
2
public
DefaultControllerFactory()
3
:
this
(
null
,
null
,
null
) {
4
}
5
6
public
DefaultControllerFactory(IControllerActivator controllerActivator)
7
:
this
(controllerActivator,
null
,
null
) {
8
}
9
10
internal
DefaultControllerFactory(IControllerActivator controllerActivator, IResolver<IControllerActivator> activatorResolver, IDependencyResolver dependencyResolver) {
11
if
(controllerActivator !=
null
) {
12
_controllerActivator = controllerActivator;
13
}
14
else
{
15
_activatorResolver = activatorResolver ??
new
SingleServiceResolver<IControllerActivator>(
16
() =>
null
,
17
new
DefaultControllerActivator(dependencyResolver),
18
"
DefaultControllerFactory contstructor
"
19
);
20
}
21
}
22
23
private
IControllerActivator ControllerActivator {
24
get
{
25
if
(_controllerActivator !=
null
) {
26
return
_controllerActivator;
27
}
28
_controllerActivator = _activatorResolver.Current;
29
return
_controllerActivator;
30
}
31
}
32
33
public
virtual
IController CreateController(RequestContext requestContext,
string
controllerName) {
34
if
(requestContext ==
null
) {
35
throw
new
ArgumentNullException(
"
requestContext
"
);
36
}
37
if
(String.IsNullOrEmpty(controllerName)) {
38
throw
new
ArgumentException(MvcResources.Common_NullOrEmpty,
"
controllerName
"
);
39
}
40
Type controllerType = GetControllerType(requestContext, controllerName);
41
IController controller = GetControllerInstance(requestContext, controllerType);
42
return
controller;
43
}
44
45
protected
internal
virtual
IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
46
47
return
ControllerActivator.Create(requestContext, controllerType);
48
}
49
50
51
52
private
class
DefaultControllerActivator : IControllerActivator {
53
Func<IDependencyResolver> _resolverThunk;
54
55
public
DefaultControllerActivator()
56
:
this
(
null
) {
57
}
58
59
public
DefaultControllerActivator(IDependencyResolver resolver) {
60
if
(resolver ==
null
) {
61
_resolverThunk = () => DependencyResolver.Current;
62
}
63
else
{
64
_resolverThunk = () => resolver;
65
}
66
}
67
68
public
IController Create(RequestContext requestContext, Type controllerType) {
69
try
{
70
return
(IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));
71
}
72
catch
(Exception ex) {
73
throw
new
InvalidOperationException(
74
String.Format(
75
CultureInfo.CurrentCulture,
76
MvcResources.DefaultControllerFactory_ErrorCreatingController,
77
controllerType),
78
ex);
79
}
80
}
81
}
82
}
83
}
在这个类中我们同样看到了和ControllerBuilder中一样的模式,也是利用SingleServiceResolver,来初始化IControllerActivator实例。如果在DependencyResolver.Current中没有找到IControllerActivator类型的话使用DefaultControllerActivator.最终利用DefaultControllerActivator.Create方法创建Controller的实例。
这里框架又提供了一个时点让我们注册自已实现的IControllerActivator类。
总结:
DependencyResolver 与 SingleServiceResolver/MutiServiceResolver 在MVC框架中配合使用的。
只要用到了ServiceResolver的地方,我们都可能通过在DependencyResolver 注册自己的行为从而改变框架的行为。
口渴中。。
不知道说清楚没,下一篇我们分析Ninject.MVC 与 asp.net MVC 的集成。
转载请注明出处: http://www.cnblogs.com/RobbinHan/archive/2011/12/05/2270707.html
本文作者: 十一月的雨 http://www.cnblogs.com/RobbinHan

