NopCommerce源码架构详解-Themes网站主题实现源码分析四

NopCommerce源码架构详解-Themes网站主题实现源码分析四

3953发表于2016-08-05

上一篇文章蓝狐给大家讲解了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:

for (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要加入如下代码:


//remove all view engines
ViewEngines.Engines.Clear();
//except the themeable razor view engine we use
ViewEngines.Engines.Add(new ThemeableRazorViewEngine());


首先要清楚默认的视图引擎,然后把我们自定义的加入进去,使其生效。


小编蓝狐