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 ...
随机推荐
- 我的Android进阶之旅------>Android颜色值(#AARRGGBB)透明度百分比和十六进制对应关系以及计算方法
我的Android进阶之旅-->Android颜色值(RGB)所支持的四种常见形式 透明度百分比和十六进制对应关系表格 透明度 十六进制 100% FF 99% FC 98% FA 97% F7 ...
- 简明python教程六----编写一个python脚本
备份程序: #!/usr/bin/python #Filename:backup_ver1.py import os import time source = ['/home/liuxj/python ...
- Git学习笔记-完全版
注意本文参考廖雪博客: http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 一:Git ...
- 名称空间(Namespaces)(转)
大致来说,命名空间只是将名称映射到对象的容器.正如你可能已经听到的,Python中的所有内容 - 字符串,列表,词典,函数,类等都是一个对象.这样的“名称与对象”的映射使我们能够通过分配给它的名称访问 ...
- oracle procedure简单的将临时表的数据插入或更新到目标表
CREATE OR REPLACE PROCEDURE DEAL_SYNC_SCH_CUSTPHONE_NEW AS CURSOR C_CURU IS SELECT * FROM CBS_COS.SC ...
- php debug函数
$debug=$_GET['debug'];//是说获取url中debug变量$debug=empty($debug)?'':$debug;//如果变量不为空,赋值为$debug,为空的话赋值 ''$ ...
- 129. Sum Root to Leaf Numbers(从根节点加到叶子节点的和)
Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a numb ...
- 用HAProxy和KeepAlived构建高可用的反向代理系统
对于访问量较大的网站来说,随着流量的增加单台服务器已经无法处理所有的请求,这时候需要多台服务器对大量的请求进行分流处理,即负载均衡.而如果实现负载均衡,必须在网站的入口部署服务器(不只是一台)对这些请 ...
- Nginx 301与302配置
说明 1.首先看一个完整代码示例,关于nginx 301 302跳转的. 301跳转设置: server { listen 80; server_name 123.com; rewrite ^/(.* ...
- 项目中使用better-scroll实现移动端滚动,报错:Cannot read property 'children' of undefined better-scroll
就是外面的盒子和要滚动的元素之间要有一层div, 插件挂载的元素是menuWrapper,可以滚动的元素是ul,在这两个元素之间加一个div元素即可解决问题.