ASP.NET MVC 中的IResolver<T> 接口
在ASP.NET MVC 的源码一些实体对象(比如 ControllerBuilder,ControllerFactory, Filters, ViewEngines 等)不再直接通过关键字new来创建实体,而是委托到 IResolver接口,而且 IResolver接口本身也比较简单,这样也提高了框架的可扩展性。由于IResolver<T>是internal,因此不会对外暴漏,在外边应该程序中是不能调用到的。
internal interface IResolver<T>
{
T Current { get; }
}
在源码中实现了IResolver接口有2个类,SingleServiceResolver 和MultiServiceResolver ,用的最多的主要是SingleServiceResolver 类
internal class SingleServiceResolver<TService> :IResolver<TService> where TService : class
{
.......
public TService Current
{
get { return _currentValueFromResolver.Value ?? _currentValueThunk() ?? _defaultValue; }
}
.......
}
在SingleServiceResolver实现接口的方法很简单,这这段代码中_currentValueFromResolver,_currentValueThunk,_defaultValue 字段的赋值都是在SingleServiceResolver构造函数中。
public SingleServiceResolver(Func<TService> currentValueThunk, TService defaultValue, string callerMethodName)
{
if (currentValueThunk == null){ throw new ArgumentNullException("currentValueThunk");}
if (defaultValue == null){ throw new ArgumentNullException("defaultValue");}
_resolverThunk = () => DependencyResolver.Current;
_currentValueFromResolver = new Lazy<TService>(GetValueFromResolver);
_currentValueThunk = currentValueThunk;
_defaultValue = defaultValue;
_callerMethodName = callerMethodName;
}
private TService GetValueFromResolver()
{
TService result = _resolverThunk().GetService<TService>();
if (result != null && _currentValueThunk() != null){
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, MvcResources.SingleServiceResolver_CannotRegisterTwoInstances, typeof(TService).Name.ToString(),
_callerMethodName));
}
return result;
}
在构造函数中_currentValueFromResolver = new Lazy<TService>(GetValueFromResolver)中构造了 Lazy<T> 类的新实例,参数为返回值为TService的委托GetValueFromResolver方法_currentValueThunk 也是一个返回值为TService的委托方法,_defaultValue 为TService 的默认值,这个3个字段都是对应的IResolver <T>接口中的Current;在GetValueFromResolver方法中首先调用的是DependencyResolver.Current类中的GetService<TService>();构造函数中的callerMethodName是记录GetValueFromResolver方法出错的异常信息。
DependencyResolver依赖解析器类
DependencyResolver的作用在msdn上是这样注释的:“为实现 System.Web.Mvc.IDependencyResolver 或公共服务定位器 IServiceLocator 接口的依赖关系解析程序提供一个注册点。”;对于IDependencyResolver接口只有2个方法,主要密度是获取服务对象(object GetService(Type serviceType);)或是服务对象列表( IEnumerable<object> GetServices(Type serviceType);)。
实现 IDependencyResolver接口的类有三个CacheDependencyResolver,DefaultDependencyResolver,DelegateBasedDependencyResolver类
private class DefaultDependencyResolver : IDependencyResolver
{
public object GetService(Type serviceType)
{
if (serviceType.IsInterface || serviceType.IsAbstract) { return null;}
try{
return Activator.CreateInstance(serviceType); }
catch
{
return null; }
}
public IEnumerable<object> GetServices(Type serviceType)
{ return Enumerable.Empty<object>(); }
}
在DefaultDependencyResolver类中的GetService方法中当参数serviceType为接口或抽象类时直接返回null,否则通过反射来创建对象;GetServices直接返回空的列表;
private class DelegateBasedDependencyResolver : IDependencyResolver
{
private Func<Type, object> _getService;
private Func<Type, IEnumerable<object>> _getServices;
public DelegateBasedDependencyResolver(Func<Type, object> getService, Func<Type, IEnumerable<object>> getServices)
{
_getService = getService;
_getServices = getServices;
}
public object GetService(Type type)
{
try
{
return _getService.Invoke(type);
}
catch
{
return null;
}
}
public IEnumerable<object> GetServices(Type type)
{
return _getServices(type);
}
}
DelegateBasedDependencyResolver 类的构造函数接收2个委托方法参数,一个是返回值为object,参数为Type的类型的委托函数,一个是返回值为 IEnumerable<object>,参数为Type的类型的委托函数,在GetService或GetServices方法中执行委托函数的Invoke方法从而创造对象,这样做的函数是把对象的创建放在外部,提高程序的扩展性。
private sealed class CacheDependencyResolver : IDependencyResolver
{
private readonly ConcurrentDictionary<Type, object> _cache = new ConcurrentDictionary<Type, object>();
private readonly ConcurrentDictionary<Type, IEnumerable<object>> _cacheMultiple = new ConcurrentDictionary<Type, IEnumerable<object>>();
private readonly Func<Type, object> _getServiceDelegate;
private readonly Func<Type, IEnumerable<object>> _getServicesDelegate;
private readonly IDependencyResolver _resolver;
public CacheDependencyResolver(IDependencyResolver resolver)
{
_resolver = resolver;
_getServiceDelegate = _resolver.GetService;
_getServicesDelegate = _resolver.GetServices;
}
public object GetService(Type serviceType)
{
return _cache.GetOrAdd(serviceType, _getServiceDelegate);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _cacheMultiple.GetOrAdd(serviceType, _getServicesDelegate);
}
}
对于CacheDependencyResolver 类就可以看出是做了一个缓存,当创建对象时,缓存里面有的话直接从缓存里面取值;
关于DefaultDependencyResolver类与IDefaultDependencyResolver类时怎么关联呢?
public class DependencyResolver
{
private static DependencyResolver _instance = new DependencyResolver();
private IDependencyResolver _current; /// <summary>
/// Cache should always be a new CacheDependencyResolver(_current).
/// </summary>
private CacheDependencyResolver _currentCache;
public DependencyResolver()
{
InnerSetResolver(new DefaultDependencyResolver());
}
public static IDependencyResolver Current
{
get { return _instance.InnerCurrent; }
}
internal static IDependencyResolver CurrentCache
{
get { return _instance.InnerCurrentCache; }
}
public IDependencyResolver InnerCurrent
{
get { return _current; }
}
/// <summary>
/// Provides caching over results returned by Current.
/// </summary>
internal IDependencyResolver InnerCurrentCache
{
get { return _currentCache; }
}
}
DefaultDependencyResolver类的属性Current就是返回IDefaultDependencyResolver接口对象,在DefaultDependencyResolver类的构造函数中默认用的DefaultDependencyResolver的类,InnerSetResolver方法主要是进行一些字段的赋值操作,而且还可以通过SetResolver方法来对_current,_currentCache字段进行赋值操作。
ASP.NET MVC 中的IResolver<T> 接口的更多相关文章
- 在Asp.Net MVC中利用快递100接口实现订阅物流轨迹功能
前言 分享一篇关于在电商系统中同步物流轨迹到本地服务器的文章,当前方案使用了快递100做为数据来源接口,这个接口是收费的,不过提供的功能还是非常强大的,有专门的售后维护团队.也有免费的方案,类似于快递 ...
- Asp.net mvc 中View 的呈现(二)
[toc] 上一节介绍了 Asp.net mvc 中除 ViewResult 外的所有的 ActionResult,这一节介绍 ViewResult. ViewResultBase ViewResul ...
- 如何在 ASP.NET MVC 中集成 AngularJS(3)
今天来为大家介绍如何在 ASP.NET MVC 中集成 AngularJS 的最后一部分内容. 调试路由表 - HTML 缓存清除 就在我以为示例应用程序完成之后,我意识到,我必须提供两个版本的路由表 ...
- ASP.NET MVC中的两个Action之间值的传递--TempData
一. ASP.NET MVC中的TempData 在ASP.NET MVC框架的ControllerBase中存在一个叫做TempData的Property,它的类型为TempDataDictiona ...
- Asp.net Mvc中利用ValidationAttribute实现xss过滤
在网站开发中,需要注意的一个问题就是防范XSS攻击,Asp.net mvc中已经自动为我们提供了这个功能.用户提交数据时时,在生成Action参数的过程中asp.net会对用户提交的数据进行验证,一旦 ...
- ASP.NET MVC中的拦截器
在ASP.NET MVC中,有三种拦截器:Action拦截器.Result拦截器和Exception拦截器, 所谓的拦截器也没有什么的,只是写一个类,继承另一个类和一个接口,顺便实现接口里面的方法而以 ...
- [转]ASP.NET MVC中你必须知道的13个扩展点
本文转自:http://www.cnblogs.com/ejiyuan/archive/2010/03/09/1681442.html ScottGu在其最新的博文中推荐了Simone Chiaret ...
- IOC 容器在 ASP.NET MVC 中的应用
IOC 容器在 ASP.NET MVC 中的应用 IOC:Inversion Of Control 翻译为控制反转,我们在面向对象软件开发过程中,一个应用程序它的底层结构可能由N种不同的构件来相互协作 ...
- ASP.NET MVC中使用Unity进行依赖注入的三种方式
在ASP.NET MVC中使用Unity进行依赖注入的三种方式 2013-12-15 21:07 by 小白哥哥, 146 阅读, 0 评论, 收藏, 编辑 在ASP.NET MVC4中,为了在解开C ...
随机推荐
- django博客项目6:Django Admin 后台发布文章
在此之前我们完成了 Django 博客首页视图的编写,我们希望首页展示发布的博客文章列表,但是它却抱怨:暂时还没有发布的文章!如它所言,我们确实还没有发布任何文章,本节我们将使用 Django 自带的 ...
- 分别用request和socket给百多发送请求
1.方式1 import socket client = socket.socket() # 百度创建连接: 阻塞 client.connect(('www.baidu.com',80)) # 问百度 ...
- Django - 文件上传、Django组件 - 分页器(paginator)
一.文件上传准备知识 - Content-Type 1.请求头 - Content-Type Content-Type指的是请求体的编码类型,常见的类型共有3种: 1)application/x-ww ...
- KMP算法最浅显理解——一看就明确
说明 KMP算法看懂了认为特别简单,思路非常easy,看不懂之前.查各种资料,看的稀里糊涂.即使网上最简单的解释,依旧看的稀里糊涂. 我花了半天时间,争取用最短的篇幅大致搞明确这玩意究竟是啥. 这里不 ...
- 自定义ActionBar图标
<style name="Theme.glTheme" parent="android:Theme.Holo"> <item name=&qu ...
- Python高级教程-高阶函数
Higher-order function(高阶函数) 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下代码: >>> abs(-10) 10 但 ...
- sersync的confxml.xml文件详解
<?xml version="1.0" encoding="ISO-8859-1"?> <head version="2.5&quo ...
- 运用SQLAlchemy
result = engine.execute(s) for row in result: Info["UserId"]=row[0] Info["UserTitle&q ...
- Linux Shell编程第3章——正则表达式
目录 正则表达式基础 正则表达式的扩展 通配 grep命令 正则表达式基础 Linux Shell以字符串作为表达式向系统传达意思.元字符(Metacharacters)是用来阐述字符表达式意义的字符 ...
- ASP.NET4 与 VS2010 Web 开发页面服务改进
转:http://blog.163.com/kele_lipeng/blog/static/81345278201132754729336/ 作者:朱先忠 本文将接着上一篇 ASP.NET4与VS20 ...