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); 获得语言记录。