最近忙於學車,抽時間將Nop的一些公用模塊添加進來,反應的一些小問題也做了修復。前篇——基於nopCommerce的開發框架(附源碼):http://www.cnblogs.com/dreling/p/6906688.html。
最新的代碼已經同布到GitHub:https://github.com/dreling8/Nop.Framework,有興趣的可以關注該項目,后續其它的一些通用模塊也會添加進去,如用戶、權限、本地化、任務、插件功能等。歡迎star給星星,你的支持是我的動力!
一、緩存模塊
nopCommerce項目緩存類層級圖
ICacheManager接口,該接口定義了數據緩存常用的方法。
CacheExtensions擴展方法對ICacheManager進行擴展。
MemoryCacheCache類,使用.net 緩存框架實現數據緩存。
PerRequestCacheManager類,實現頁面請求級的數據緩存。
RedisCacheManager類,實現Redis數據緩存類。
NopNullCache類,空的數據緩存類實現。
IRedisConnectionWrapper接口,redis連接封裝接口。
RedisConnectionWrapper類,redis連接實現。
緩存的使用
在依賴注入中(DependencyRegistrar),將緩存注入到IOC容器中,系統默認使用MemoryCacheCache,如果想使用redis緩存可在配置模塊啟用並設置相關參數。
//cache managers
if (config != null && config.RedisCachingEnabled) { builder.RegisterType<RedisConnectionWrapper>().As<IRedisConnectionWrapper>().SingleInstance(); builder.RegisterType<RedisCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").InstancePerLifetimeScope(); } else { builder.RegisterType<MemoryCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").SingleInstance(); } builder.RegisterType<PerRequestCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_per_request").InstancePerLifetimeScope();
在用戶操作服務UserActivityService中可以了解到,數據緩存是如何處理的,在數據檢索時,直接從緩存取數據,其他方法均根據相關正則表達式移除ActivityLogType的所有緩存,以避免讀取到臟數據。
protected virtual IList<ActivityLogTypeForCaching> GetAllActivityTypesCached() { //cache
string key = string.Format(ACTIVITYTYPE_ALL_KEY); return _cacheManager.Get(key, () => { var result = new List<ActivityLogTypeForCaching>(); var activityLogTypes = GetAllActivityTypes(); foreach (var alt in activityLogTypes) { var altForCaching = new ActivityLogTypeForCaching { Id = alt.Id, SystemKeyword = alt.SystemKeyword, Name = alt.Name, Enabled = alt.Enabled }; result.Add(altForCaching); } return result; }); }
二、設置模塊
Nop的設置功能實現比較有意思,先看類層級圖。
ILocalizedEntity接口,暫時忽略該接口。
ISettings接口,設置接口。
Setting類,設置實體類。
CommonSettings類,一個實現ISettings接口的通用設置類。
通過Autofac的IRegistrationSource接口,將所有的設置類注入。
public class SettingsSource : IRegistrationSource { static readonly MethodInfo BuildMethod = typeof(SettingsSource).GetMethod( "BuildRegistration", BindingFlags.Static | BindingFlags.NonPublic); public IEnumerable<IComponentRegistration> RegistrationsFor( Service service, Func<Service, IEnumerable<IComponentRegistration>> registrations) { var ts = service as TypedService; if (ts != null && typeof(ISettings).IsAssignableFrom(ts.ServiceType)) { var buildMethod = BuildMethod.MakeGenericMethod(ts.ServiceType); yield return (IComponentRegistration)buildMethod.Invoke(null, null); } } static IComponentRegistration BuildRegistration<TSettings>() where TSettings : ISettings, new() { return RegistrationBuilder .ForDelegate((c, p) => { ////var currentStoreId = c.Resolve<IStoreContext>().CurrentStore.Id;
//uncomment the code below if you want load settings per store only when you have two stores installed. //var currentStoreId = c.Resolve<IStoreService>().GetAllStores().Count > 1 // c.Resolve<IStoreContext>().CurrentStore.Id : 0; //although it's better to connect to your database and execute the following SQL: //DELETE FROM [Setting] WHERE [StoreId] > 0
return c.Resolve<ISettingService>().LoadSetting<TSettings>(); }) .InstancePerLifetimeScope() .CreateRegistration(); } public bool IsAdapterForIndividualComponents { get { return false; } } }
如何添加相關的設置
像commonsetting一樣,只需要定義一個實現空接口ISettings的類,然后的數據表中添加相關的配置,數據庫中Name值對應:類名 + . + 屬性名,和接口注入方式一樣,不過這里使用類注入。另外需要注意的是在Nop.Core項目ComponentModel目錄下的GenericDictionaryTypeConverter和GenericListTypeConverter類中重寫了泛型List和泛型Dictionary的CanConvertFrom和ConvertFrom方法,使得數據庫中存儲字符串能轉換成對應的List和Dictionary,如List存儲時我們只需要將多個數據使用英文符號(,)分隔符即可。

public class CommonSettings : ISettings { public CommonSettings() { IgnoreLogWordlist = new List<string>(); } /// <summary>
/// Gets or sets a value indicating whether stored procedures are enabled (should be used if possible) /// </summary>
public bool UseStoredProceduresIfSupported { get; set; } /// <summary>
/// Gets or sets a value indicating whether to use stored procedure (if supported) for loading categories (it's much faster in admin area with a large number of categories than the LINQ implementation) /// </summary>
public bool UseStoredProcedureForLoadingCategories { get; set; } /// <summary>
/// Gets or sets a value indicating whether 404 errors (page or file not found) should be logged /// </summary>
public bool Log404Errors { get; set; } /// <summary>
/// Gets or sets ignore words (phrases) to be ignored when logging errors/messages /// </summary>
public List<string> IgnoreLogWordlist { get; set; } }
public class HomeController : Controller { public ILogger _logger; public IUserActivityService _userActivityService; public CommonSettings _commonSettings; public HomeController( ILogger logger, IUserActivityService userActivityService, CommonSettings commonSetting) { _logger = logger; _userActivityService = userActivityService; _commonSettings = commonSettings; } public ActionResult Index() { TestSettings(); TestLogger(); return View(); } private void TestSettings() { var s = _commonSettings.IgnoreLogWordlist; } private void TestLogger() { _logger.InsertLog(LogLevel.Information, "index visit"); _userActivityService.InsertActivity(ActivityLogTypeEnum.AddUser, "添加用戶{0},{1}", new string[2] { "aaaa", "bbb" }); } }
數據庫配置(IDataProvider)
之前使用web.config配置的connectionStrings,現在改為IDataProvider的實現來統一配置相關的參數,特別提示數據庫配置文件在App_Data目錄下的Settings.txt,如果沒有新建一個,系統運行后會根據EntityFramework的數據映射自動創建相關表。
DataProvider: sqlserver
DataConnectionString: Data Source=.;Initial Catalog=nopFramework;Integrated Security=False;Persist Security Info=False;User ID=sa;Password=sa1234
三、日志模塊

ILogger接口,日志接口。
NullLogger類,Logger接口空實現。
DefaultLogger類,Nop默認的日志接口實現。
LoggingExtensions類,日志擴展,使用日志的擴展方法來存儲不同級別的日志記錄。
IUserActivityService接口,用戶操作服務接口。
UserActivityService類,用戶操作服務實現。
Nop沒有使用類似於Log4net的開源日志記錄組件,當然如果你想使用可以通過實現接口來引入。
IUserActivityService用於記錄用戶操作的記錄,需要在ActivityLogType表配置好用戶操作的類型,這里優化了一下,將類型通過枚舉列出來,這樣在記錄用戶操作的時候不至於輸錯參數。
在首頁的控制器中加入測試代碼,日志和操作記錄都添加到了數據庫中。
private void TestLogger() { _logger.InsertLog(LogLevel.Information, "index visit"); _userActivityService.InsertActivity(ActivityLogTypeEnum.AddUser, "添加用戶{0},{1}", new string[2] { "aaaa", "bbb" }); }
至此,開發框架中添加了常用的緩存、網站設置、系統日志、用戶操作日志功能。

