NopCommerce源码架构详解-Themes网站主题实现源码分析4
上一篇文章蓝狐给大家讲解了NopCommerce主题相关的源码里面的ThemeContext和ThemeProvider。
概述
NopCommerce源码架构详解-Themes网站主题实现源码分析4。
内容
上一篇文章蓝狐给大家讲解了NopCommerce主题相关的源码里面的ThemeContext和ThemeProvider。
今天重点来讲讲ThemeableVirtualPathProviderViewEngine和ThemeableRazorViewEngine类。下面是相关类的类图:

从名字可以看出来这两个类是关于mvc视图引擎的。其中ThemeableRazorViewEngine是ThemeableVirtualPathProviderViewEngine的子类。
父类ThemeableVirtualPathProviderViewEngine又继承于VirtualPathProviderViewEngine类。
VirtualPathProviderViewEngine成员:

VirtualPathProviderViewEngine类是Asp.NET MVC框架下自带的类。里面最重要是方法就是FindView和CreateView,分别用于查找对应的视图和创建视图。
ThemeableVirtualPathProviderViewEngine类重写了FindView和CreateView方法,置入了主题Theme的概念。如下图:

类ThemeableVirtualPathProviderViewEngine,查找视图的方法调用顺序如下:
FindView=>GetPath=>GetPathFromGeneralName=>ViewLocation.Format
其中GetPathFromGeneralName很关键,调用了类ViewLocation的Format:
(int i = 0; i < locations.Count; i++) { ViewLocation location = locations[i]; string virtualPath = location.Format(name, controllerName, areaName, theme); //根据请求的Url,获取带主题的虚拟路径 //... }
//根据请求的Url,获取带主题的虚拟路径
string virtualPath = location.Format(name, controllerName, areaName, theme);
location的Format方法是在Location类里面定义的:
public class ViewLocation { protected readonly string _virtualPathFormatString; public ViewLocation(string virtualPathFormatString) { _virtualPathFormatString = virtualPathFormatString; } public virtual string Format(string viewName, string controllerName, string areaName, string theme) { return string.Format(CultureInfo.InvariantCulture, _virtualPathFormatString, viewName, controllerName, theme); } }
可以看到ViewLocation最终调用的是string.Format,而且第一个参数为视图名,第二为参数为控制器名,第三个为主题名。
对应的_virtualPathFormatString视图虚拟路径为格式是类ThemeableRazorViewEngine的构造函数中定义的。如下:

可以看到正好吻合。可以从上图中看到nop查找视图会首先去当前生效主题文件目录下查找(主题路径规则),然后才按默认规则查找。因为带~Themes的在前面。

这样,如果在视图中调用@Html.Partial(Header)视图引擎自动会先去主题目录查找名为Header.cshtml的。

最后很关键,要使Nop中自定义的视图引擎ThemeableRazorViewEngine生效,在Application_Start要加入如下代码:
//move all view engines ViewEngines.Engines.Clear(); //except the themeable razor view engine we use ViewEngines.Engines.Add(new ThemeableRazorViewEngine());
首先要清楚默认的视图引擎,然后把我们自定义的加入进去,使其生效。