NOP源码分析 八---set的存储

我们已经把ISetting的基本实现都过了一遍,但好像它的值如何取出来的,还不知道。

其实通过上节我们可知道 ,最终他是通过SettingService.cs类GetAllSettingsCached方法进行。内部有如下代码:

var query = from s in _settingRepository.TableNoTracking
                            orderby s.Name, s.StoreId
                            select s;

AsNoTracking是EF的一个功能,就是不跟踪状态。只读的情况下用它提高效率,可百度。最终是通过settingRepository从数据库取出的数值。当然表是Setting表,通过声明private readonly IRepository<Setting> _settingRepository; 就可知道。

好了,现在所有知道所有的ISetting的继承子类  都是通过读取数据库的Setting表得到的数值。

没想到LocalizationSettings引申出这么多,我们还是要回到当初那个位置,从那里继续。回到WebWorkContext类的方法WorkingLanguage。

Language detectedLanguage = null;
                if (_localizationSettings.SeoFriendlyUrlsForLanguagesEnabled)
                {
                    //get language from URL
                    detectedLanguage = GetLanguageFromUrl();
                }

从数据库得到的SeoFriendlyUrlsForLanguagesEnabled是False,所以继续往下。

if (detectedLanguage == null && _localizationSettings.AutomaticallyDetectLanguage)

AutomaticallyDetectLanguage数据库该值也是false.

返回false的都不执行,我们接着往下:

var allLanguages = _languageService.GetAllLanguages(storeId: _storeContext.CurrentStore.Id);

这一句,从词义看就是返回所有语言。

元旦过了,继续写咱的笔记。

找到语言服务的实现类 amespace Nop.Services.Localization下的LanguageService : ILanguageService。方法如下:

/// <summary>
        /// Gets all languages
        /// </summary>
        /// <param name="storeId">Load records allowed only in a specified store; pass 0 to load all records</param>
        /// <param name="showHidden">A value indicating whether to show hidden records</param>
        /// <returns>Language collection</returns>
        public virtual IList<Language> GetAllLanguages(bool showHidden = false, int storeId = 0)
        {
            string key = string.Format(LANGUAGES_ALL_KEY, showHidden);
            var languages = _cacheManager.Get(key, () =>
            {
                var query = _languageRepository.Table;
                if (!showHidden)
                    query = query.Where(l => l.Published);
                query = query.OrderBy(l => l.DisplayOrder);
                return query.ToList();
            });

            //store mapping
            if (storeId > 0)
            {
                languages = languages
                    .Where(l => _storeMappingService.Authorize(l, storeId))
                    .ToList();
            }
            return languages;
        }

个人现在觉得 ,好像storeId 是用来管理多点的吧,或者多个存储库。

第一句  格式化KEY。

第二句 通过KEY,从缓存获得这个表达式的值,缓存60分钟.

表达式函数你用到的存储库声明如下:

private readonly IRepository<Language> _languageRepository;

可见  查的数据库表是Language表,获得所有已发布的,最后根据DisplayOrder排序。返回语言列表。

执行 下一句:

//find current customer language
                var languageId = this.CurrentCustomer.GetAttribute<int>(SystemCustomerAttributeNames.LanguageId,

currentCustomer代码如下:

/// <summary>
        /// Gets or sets the current customer
        /// </summary>
        public virtual Customer CurrentCustomer
        {
            get
            {
                if (_cachedCustomer != null)
                    return _cachedCustomer;

                Customer customer = null;
                if (_httpContext == null || _httpContext is FakeHttpContext)
                {
                    //check whether request is made by a background task
                    //in this case return built-in customer record for background task
                    customer = _customerService.GetCustomerBySystemName(SystemCustomerNames.BackgroundTask);
                }

                //check whether request is made by a search engine
                //in this case return built-in customer record for search engines 
                //or comment the following two lines of code in order to disable this functionality
                if (customer == null || customer.Deleted || !customer.Active)
                {
                    if (_userAgentHelper.IsSearchEngine())
                        customer = _customerService.GetCustomerBySystemName(SystemCustomerNames.SearchEngine);
                }

                //registered user
                if (customer == null || customer.Deleted || !customer.Active)
                {
                    customer = _authenticationService.GetAuthenticatedCustomer();
                }

                //impersonate user if required (currently used for 'phone order' support)
                if (customer != null && !customer.Deleted && customer.Active)
                {
                    var impersonatedCustomerId = customer.GetAttribute<int?>(SystemCustomerAttributeNames.ImpersonatedCustomerId);
                    if (impersonatedCustomerId.HasValue && impersonatedCustomerId.Value > 0)
                    {
                        var impersonatedCustomer = _customerService.GetCustomerById(impersonatedCustomerId.Value);
                        if (impersonatedCustomer != null && !impersonatedCustomer.Deleted && impersonatedCustomer.Active)
                        {
                            //set impersonated customer
                            _originalCustomerIfImpersonated = customer;
                            customer = impersonatedCustomer;
                        }
                    }
                }

                //load guest customer
                if (customer == null || customer.Deleted || !customer.Active)
                {
                    var customerCookie = GetCustomerCookie();
                    if (customerCookie != null && !String.IsNullOrEmpty(customerCookie.Value))
                    {
                        Guid customerGuid;
                        if (Guid.TryParse(customerCookie.Value, out customerGuid))
                        {
                            var customerByCookie = _customerService.GetCustomerByGuid(customerGuid);
                            if (customerByCookie != null &&
                                //this customer (from cookie) should not be registered
                                !customerByCookie.IsRegistered())
                                customer = customerByCookie;
                        }
                    }
                }

                //create guest if not exists
                if (customer == null || customer.Deleted || !customer.Active)
                {
                    customer = _customerService.InsertGuestCustomer();
                }


                //validation
                if (!customer.Deleted && customer.Active)
                {
                    SetCustomerCookie(customer.CustomerGuid);
                    _cachedCustomer = customer;
                }

                return _cachedCustomer;
            }
            set
            {
                SetCustomerCookie(value.CustomerGuid);
                _cachedCustomer = value;
            }
        }

我们先分析customer = _customerService.GetCustomerBySystemName(SystemCustomerNames.BackgroundTask); 这一句。

public virtual Customer GetCustomerBySystemName(string systemName)
        {
            if (string.IsNullOrWhiteSpace(systemName))
                return null;

            var query = from c in _customerRepository.Table
                        orderby c.Id
                        where c.SystemName == systemName
                        select c;
            var customer = query.FirstOrDefault();
            return customer;
        }

就是从Customer表获得systemName相等的customer记录。systemName 是SystemCustomerNames.BackgroundTask,就是字符串BackgroundTask。

然后研究Customer的GetAttribute方法,这是一个扩展方法:

public static TPropType GetAttribute<TPropType>(this BaseEntity entity,
            string key, IGenericAttributeService genericAttributeService, int storeId = 0)
        {
            if (entity == null)
                throw new ArgumentNullException("entity");

            string keyGroup = entity.GetUnproxiedEntityType().Name;

            var props = genericAttributeService.GetAttributesForEntity(entity.Id, keyGroup);
            //little hack here (only for unit testing). we should write ecpect-return rules in unit tests for such cases
            if (props == null)
                return default(TPropType);
            props = props.Where(x => x.StoreId == storeId).ToList();
            if (props.Count == 0)
                return default(TPropType);

            var prop = props.FirstOrDefault(ga =>
                ga.Key.Equals(key, StringComparison.InvariantCultureIgnoreCase)); //should be culture invariant

            if (prop == null || string.IsNullOrEmpty(prop.Value))
                return default(TPropType);

            return CommonHelper.To<TPropType>(prop.Value);
        }

string keyGroup = entity.GetUnproxiedEntityType().Name;  获得这个类的类型名称。

找到IGenericAttributeService的实现类GenericAttributeService。方法:

/// <summary>
        /// Get attributes
        /// </summary>
        /// <param name="entityId">Entity identifier</param>
        /// <param name="keyGroup">Key group</param>
        /// <returns>Get attributes</returns>
        public virtual IList<GenericAttribute> GetAttributesForEntity(int entityId, string keyGroup)
        {
            string key = string.Format(GENERICATTRIBUTE_KEY, entityId, keyGroup);
            return _cacheManager.Get(key, () =>
            {
                var query = from ga in _genericAttributeRepository.Table
                            where ga.EntityId == entityId &&
                            ga.KeyGroup == keyGroup
                            select ga;
                var attributes = query.ToList();
                return attributes;
            });
        }

private readonly IRepository<GenericAttribute> _genericAttributeRepository; 是用的库的声明,数据就是从GenericAttribute表里根据EntityId 和KeyGroup 获得的。

最后 var language = allLanguages.FirstOrDefault(x => x.Id == languageId); 获得语言记录。

猜你喜欢

转载自www.cnblogs.com/runit/p/4196093.html