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

我在前面一篇文章我们对讲了nop的Themes网站主题有了一个大概的概念。下面我们开始来看看到底里面的核心原理,分别针对里面重要的类进行一些关键点介绍。

NopCommerce源码架构详解概述

文章目录

概述

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

内容

我在前面一篇文章我们对讲了nop的Themes网站主题有了一个大概的概念。下面我们开始来看看到底里面的核心原理,分别针对里面重要的类进行一些关键点介绍。下面是主要的类的类图和方法。

2020-04-23-20-10-57

可以从上图中看到这些类的关系。入口是ThemeContext类,它是针对接口IThemeContext的真正实现,接口很简单,它只有一个方法。

namespace Nop.Web.Framework.Themes
{
    /// <summary>
    /// Work context
    /// </summary>
    public interface IThemeContext
    {
        /// <summary>
        /// 获取系统当前主题的名称
        /// </summary>
        string WorkingThemeName { get; set; }
    }
}

Nop.Web.Framework.Themes.ThemeContext.cs:

using System;
using System.linq;
using Nop.Core;
using Nop.Core.Domain;
using Nop.Core.Domain.Customers;
using Nop.Services.Common;

namespace Nop.Web.Framework.Themes
{
    /// <summary>
    /// Theme context
    /// </summary>
    public partial class ThemeContext : IThemeContext
    {
        private readonly IWorkContext _workContext;
        private readonly IStoreContext _storeContext;
        private readonly IGenericAttributeService _genericAttributeService;
        private readonly StoreInformationSettings _storeInformationSettings;
        private readonly IThemeProvider _themeProvider;

        private bool _themeIsCached;
        private string _cachedThemeName;

        public ThemeContext(IWorkContext workContext,
            IStoreContext storeContext,
            IGenericAttributeService genericAttributeService, 
            StoreInformationSettings storeInformationSettings, 
            IThemeProvider themeProvider)
        {
            this._workContext = workContext;
            this._storeContext = storeContext;
            this._genericAttributeService = genericAttributeService;
            this._storeInformationSettings = storeInformationSettings;
            this._themeProvider = themeProvider;
        }

        /// <summary>
        /// 属性:读取或设置系统主题名称
        /// </summary>
        public string WorkingThemeName
        {
            get
            {
                if (_themeIsCached)
                    return _cachedThemeName;

                string theme = "";
                if (_storeInformationSettings.AllowCustomerToSelectTheme)
                {
                    if (_workContext.CurrentCustomer != null)
                        theme = _workContext.CurrentCustomer.GetAttribute<string>(SystemCustomerAttributeNames.WorkingThemeName, _genericAttributeService, _storeContext.CurrentStore.Id);
                }

                //默认商店主题
                if (string.IsNullOrEmpty(theme))
                    theme = _storeInformationSettings.DefaultStoreTheme;

                //ensure that theme exists
                if (!_themeProvider.ThemeConfigurationExists(theme))
                {
                    //如果不存在默认主题就加载主题集合中的第一个主题
                    var themeInstance = _themeProvider.GetThemeConfigurations()
                        .FirstOrDefault();
                    if (themeInstance == null)
                        throw new Exception("No theme could be loaded");
                    theme = themeInstance.ThemeName;
                }

                //cache theme
                this._cachedThemeName = theme;
                this._themeIsCached = true;
                return theme;
            }
            set
            {
                if (!_storeInformationSettings.AllowCustomerToSelectTheme)
                    return;

                if (_workContext.CurrentCustomer == null)
                    return;

                _genericAttributeService.SaveAttribute(_workContext.CurrentCustomer, SystemCustomerAttributeNames.WorkingThemeName, value, _storeContext.CurrentStore.Id);

                //clear cache
                this._themeIsCached = false;
            }
        }
    }
}

注意:类ThemeContext构造函数的参数都是接口类型,这样可以通过Autofac进行依赖注入,从而降低了对具体实现的耦合。最后一个参数为IThemeProvider类型。

Nop.Web.Framework.Themes.IThemeProvider:

System.Collections.Generic;

namespace Nop.Web.Framework.Themes
{
    public partial interface IThemeProvider
    {
        ThemeConfiguration GetThemeConfiguration(string themeName);//获取指定主题配置信息

        IList<ThemeConfiguration> GetThemeConfigurations();//获取全部主题的配置信息集合

        bool ThemeConfigurationExists(string themeName);//判断主题是否存在
    }
}

Nop.Web.Framework.Themes.ThemeProvider::

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using Nop.Core;

namespace Nop.Web.Framework.Themes
{
    /// <summary>
    /// 主题全部集合:项目的路径~/Themes/,一个主题一个目录,遍历目录并加载每天个主题目录下面的配置信息theme.config
    /// </summary>
    public partial class ThemeProvider : IThemeProvider
    {
        #region Fields

        private readonly IList<ThemeConfiguration> _themeConfigurations = new List<ThemeConfiguration>();
        private readonly string _basePath = string.Empty;

        #endregion

        #region Constructors

        public ThemeProvider()
        {
            _basePath = CommonHelper.MapPath("~/Themes/");
            LoadConfigurations();
        }

        #endregion

        #region IThemeProvider

        public ThemeConfiguration GetThemeConfiguration(string themeName)
        {
            return _themeConfigurations
                .SingleOrDefault(x => x.ThemeName.Equals(themeName, StringComparison.InvariantCultureIgnoreCase));
        }

        public IList<ThemeConfiguration> GetThemeConfigurations()
        {
            return _themeConfigurations;
        }

        public bool ThemeConfigurationExists(string themeName)
        {
            return GetThemeConfigurations().Any(configuration => configuration.ThemeName.Equals(themeName, StringComparison.InvariantCultureIgnoreCase));
        }

        #endregion

        #region Utility

        /// <summary>
        /// 从主题所在根目录开始遍历,并加载这些主题
        /// </summary>
        private void LoadConfigurations()
        {
            //TODO:Use IFileStorage?
            foreach (string themeName in Directory.GetDirectories(_basePath))
            {
                var configuration = CreateThemeConfiguration(themeName);
                if (configuration != null)
                {
                    _themeConfigurations.Add(configuration);
                }
            }
        }

        /// <summary>
        /// 读取主题配置文件里面配置信息并封装成一个对象ThemeConfiguration
        /// </summary>
        /// <param name="themePath"></param>
        /// <returns></returns>
        private ThemeConfiguration CreateThemeConfiguration(string themePath)
        {
            var themeDirectory = new DirectoryInfo(themePath);
            var themeConfigFile = new FileInfo(Path.Combine(themeDirectory.FullName, "theme.config"));

            if (themeConfigFile.Exists)
            {
                var doc = new XmlDocument();
                doc.Load(themeConfigFile.FullName);
                return new ThemeConfiguration(themeDirectory.Name, themeDirectory.FullName, doc);
            }

            return null;
        }

        #endregion
    }
}

可以看到的有插件的根目录为~/Themes/,并在构造函数中调用LoadConfigurations方法来加载检测到的插件的的有配置信息。

原文出处:蓝狐软件工作室【蓝狐】

原文链接:http://m.lanhusoft.com/Article/349.html

本文观点不代表 .Net中文网 立场,转载请联系原作者。

发表评论

登录后才能评论