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

浙公网安备 33010602011771号