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 ...
随机推荐
- Hibernate简单配置
1.配置构建路径,加载用户库,hibernate4.3.8 MySQL-Driver 2.写User.java 纯POJO+持久化注解=PO @Entity @Table(name=&quo ...
- 系列文章(二):从WLAN的安全威胁,解析电信诈骗的技术症结——By Me
导读:互联网的无线接入已经成为大趋势,其中无线局域网(又称为WLAN,Wireless Local AreaNetwork)以其使用方便.组网灵活.可扩展性好.成本低等优点,成为互联网特别是移动互联网 ...
- 《Redis官方文档》用Redis构建分布式锁
用Redis构建分布式锁 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但是这些库实现的方式差别很大,而且很多简 ...
- python爬取当当网的书籍信息并保存到csv文件
python爬取当当网的书籍信息并保存到csv文件 依赖的库: requests #用来获取页面内容 BeautifulSoup #opython3不能安装BeautifulSoup,但可以安装Bea ...
- PHP获取与操作php.ini文件的几个函数示例
php有一套设置和获取配置信息的函数,用于设置与修改相关参数信息. 1.ini_get()获取配置参数,ini_set()设置配置参数 <?php 2.ini_get_all()获取所有配置 ...
- go——函数
1.定义 函数是结构化编程的最小单元模式.它将复杂的算法过程分解为若干个较小任务,隐藏相关细节,使程序结构更加清晰,易于维护.函数被设计成相对独立,通过接收输入参数完成一段算法指令,输出或存储相关结果 ...
- struts2基础——需要注意的几点
struts是流行和成熟的基于MVC设计模式的web应用程序框架,使用struts可以帮助我们减少运用MVC设计模型来开发web应用的时间. 目录: 一.struts2的工作原理及文件结构 二.三种访 ...
- python之路 线程、进程、协程、队列、python-memcache、python-redis
一.线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. #!/usr/bin/env python # -*- coding:utf-8 -*- import threa ...
- URAL - 1900 Brainwashing Device
While some people travel in space from planet to planet and discover new worlds, the others who live ...
- hadoop2.7.x运行wordcount程序卡住在INFO mapreduce.Job: Running job:job _1469603958907_0002
一.抛出问题 Hadoop集群(全分布式)配置好后,运行wordcount程序测试,发现每次运行都会卡住在Running job处,然后程序就呈现出卡死的状态. wordcount运行命令:[hado ...