带你读开源—ASP.NET_MVC(八)

rufengit 2016-09-04 03:10:53
加精
上篇说到GetControllerTypeWithinNamespaces方法,我们跟踪进入其定义后,发现其调用了ControllerTypeCache.GetControllerTypes方法,从ControllerTypeCache这个名称我们就可以猜测出,它是从某个缓存中查找控制器类型的。跟踪之,进入代码段1。
  public ICollection<Type> GetControllerTypes(string controllerName, HashSet<string> namespaces)
{
HashSet<Type> matchingTypes = new HashSet<Type>();

ILookup<string, Type> namespaceLookup;
if (_cache.TryGetValue(controllerName, out namespaceLookup))
{
// this friendly name was located in the cache, now cycle through namespaces
if (namespaces != null)
{
foreach (string requestedNamespace in namespaces)
{
foreach (var targetNamespaceGrouping in namespaceLookup)
{
if (IsNamespaceMatch(requestedNamespace, targetNamespaceGrouping.Key))
{
matchingTypes.UnionWith(targetNamespaceGrouping);
}
}
}
}
else
{
// if the namespaces parameter is null, search *every* namespace
foreach (var namespaceGroup in namespaceLookup)
{
matchingTypes.UnionWith(namespaceGroup);
}
}
}

return matchingTypes;
}

代码段 1

代码段1中,我们看语句【_cache.TryGetValue(controllerName, out namespaceLookup)】,其中的_cache是一个字典对象,涉及到它的操作见代码段2。
public void EnsureInitialized(IBuildManager buildManager)
{
if (_cache == null)
{
lock (_lockObj)
{
if (_cache == null)
{
List<Type> controllerTypes = TypeCacheUtil.GetFilteredTypesFromAssemblies(TypeCacheName, IsControllerType, buildManager);
var groupedByName = controllerTypes.GroupBy(
t => t.Name.Substring(0, t.Name.Length - "Controller".Length),
StringComparer.OrdinalIgnoreCase);
_cache = groupedByName.ToDictionary(
g => g.Key,
g => g.ToLookup(t => t.Namespace ?? String.Empty, StringComparer.OrdinalIgnoreCase),
StringComparer.OrdinalIgnoreCase);
}
}
}
}

代码段 2

在代码段2中找到GetFilteredTypesFromAssemblies方法,跟踪进入其定义(代码段3),里面又有三条很扎眼的注释:【// first, try reading from the cache on disk】、【// if reading from the cache failed, enumerate over every assembly looking for a matching type】、【// finally, save the cache back to disk】,看来微软开源项目组很喜欢“三”这个数字,呵呵!给大家大概翻译一下:首先,尝试读取磁盘缓存;如果缓存读取失败,则枚举所有程序集,以寻找匹配的类型;最后,把缓存保存回磁盘。这就验证了MVC框架从缓存获取控制器类型的猜测。
  public static List<Type> GetFilteredTypesFromAssemblies(string cacheName, Predicate<Type> predicate, IBuildManager buildManager)
{
TypeCacheSerializer serializer = new TypeCacheSerializer();

// first, try reading from the cache on disk
List<Type> matchingTypes = ReadTypesFromCache(cacheName, predicate, buildManager, serializer);
if (matchingTypes != null)
{
return matchingTypes;
}

// if reading from the cache failed, enumerate over every assembly looking for a matching type
matchingTypes = FilterTypesInAssemblies(buildManager, predicate).ToList();

// finally, save the cache back to disk
SaveTypesToCache(cacheName, matchingTypes, buildManager, serializer);

return matchingTypes;
}

代码段 3

好了,现在我们得到了控制器的类型。我们再回到DefaultControllerFactory的CreateController方法,找到语句【IController controller = GetControllerInstance(requestContext, controllerType);】,这句的作用是实例化IController接口。跟踪GetControllerInstance的定义,见代码段4。
 protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404,
String.Format(
CultureInfo.CurrentCulture,
MvcResources.DefaultControllerFactory_NoControllerFound,
requestContext.HttpContext.Request.Path));
}
if (!typeof(IController).IsAssignableFrom(controllerType))
{
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture,
MvcResources.DefaultControllerFactory_TypeDoesNotSubclassControllerBase,
controllerType),
"controllerType");
}
return ControllerActivator.Create(requestContext, controllerType);
}

代码段 4

代码段4最后一句【return ControllerActivator.Create(requestContext, controllerType);】,正是这一句创建了IController实例。
OK,控制器的实例化完成了。

...全文
1594 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_36121760 2016-09-12
  • 打赏
  • 举报
回复
6666666666666666666666666666666
kcgtcdy 2016-09-08
  • 打赏
  • 举报
回复
learning~
dwa4821 2016-09-08
  • 打赏
  • 举报
回复
1111111111111
Linuxwell 2016-09-08
  • 打赏
  • 举报
回复
好好学习天天向上
dash_chenjh 2016-09-06
  • 打赏
  • 举报
回复
很棒的分享!!
Chng100818 2016-09-06
  • 打赏
  • 举报
回复
嘩,好東西
  • 打赏
  • 举报
回复
感谢分享
爱睡觉的阿狸 2016-09-05
  • 打赏
  • 举报
回复
snail_xin 2016-09-05
  • 打赏
  • 举报
回复
感谢额,很不错
jjj9882007 2016-09-05
  • 打赏
  • 举报
回复
66666666666666666666666
insus 2016-09-04
  • 打赏
  • 举报
回复
关注,研究与学习中......

62,047

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧