NET的内存缓存使用实现本地化模块

首先我们需要的资源需要列一下:
1、命名空间System.Runtime.Caching;
2、Autofac、Autofac.Mvc
3、KendoUiWEB
4、StackExchange.Redis.StrongName(redis缓存,因为我没有实现,所有可以忽略)

打开Visual Studio(我用的15)新建项目,添加以上相关(Caching添加引用,其他Nuget)。然后看我的文件夹配置
这里写图片描述

1、Caching 配置,首先声明接口ICacheManager

 public interface ICacheManager : IDisposable
    {
        /// <summary>
        /// 获取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        T Get<T>(string key);

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="data"></param>
        /// <param name="cacheTime"></param>
        void Set(string key, object data, int cacheTime);

        /// <summary>
        /// 是否存在
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        bool IsSet(string key);

        /// <summary>
        /// 移除
        /// </summary>
        /// <param name="key"></param>
        void Remove(string key);

        void RemoveByPattern(string pattern);

        void Clear();
    }

实现接口MemoryCacheManager,因为我用内存实现的(你们可以写个Redis实现的),并且接口已经写了注释,看接口的吧

/// <summary>
    /// 内存缓存管理器
    /// </summary>
    public partial class MemoryCacheManager : ICacheManager
    {
        /// <summary>
        /// 内存对象
        /// </summary>
        protected ObjectCache Cache
        {
            get
            {
                return MemoryCache.Default;
            }
        }

        public virtual T Get<T>(string key)
        {
            return (T)Cache[key];
        }

        public virtual void Set(string key, object data, int cacheTime)
        {
            if (data == null)
                return;

            var policy = new CacheItemPolicy();
            policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
            Cache.Add(new CacheItem(key, data), policy);
        }

        public virtual bool IsSet(string key)
        {
            return (Cache.Contains(key));
        }

        public virtual void Remove(string key)
        {
            Cache.Remove(key);
        }

        public virtual void RemoveByPattern(string pattern)
        {
            this.RemoveByPattern(pattern, Cache.Select(p => p.Key));
        }
        public virtual void Clear()
        {
            foreach (var item in Cache)
                Remove(item.Key);
        }

        public virtual void Dispose()
        {
        }
    }

其次,要对缓存增加扩展类方便我们使用CacheExtensions。

/// <summary>
    /// 缓存扩展类
    /// </summary>
    public static class CacheExtensions
    {
        /// <summary>
        /// 获取缓存数据
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="cacheManager">缓存对象</param>
        /// <param name="key">Key</param>
        /// <param name="acquire">表达式</param>
        /// <returns></returns>
        public static T Get<T>(this ICacheManager cacheManager, string key, Func<T> acquire)
        {
            return Get(cacheManager, key, 60, acquire);
        }

        /// <summary>
        /// 获取缓存数据
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="cacheManager">缓存对象</param>
        /// <param name="key">Key</param>
        /// <param name="cacheTime">缓存时间</param>
        /// <param name="acquire">表达式</param>
        /// <returns></returns>
        public static T Get<T>(this ICacheManager cacheManager, string key, int cacheTime, Func<T> acquire)
        {
            if (cacheManager.IsSet(key))
            {
                return cacheManager.Get<T>(key);
            }

            var result = acquire();
            if (cacheTime > 0)
                cacheManager.Set(key, result, cacheTime);
            return result;
        }
        /// <summary>
        /// 移除
        /// </summary>
        /// <param name="cacheManager"></param>
        /// <param name="pattern"></param>
        /// <param name="keys"></param>
        public static void RemoveByPattern(this ICacheManager cacheManager, string pattern, IEnumerable<string> keys)
        {
            var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
            foreach (var key in keys.Where(p => regex.IsMatch(p.ToString())).ToList())
                cacheManager.Remove(key);
        }
    }

2、配置本地化资源,在项目中增加文件夹Localization,在文件夹里面建立文件夹Resource(当然你可以通过数据库实现本地化资源管理)。在Localization声明接口ILocalizationSource代码如下:

/// <summary>
    /// 本地化服务
    /// </summary>
    public interface ILocalizationSource
    {

        /// <summary>
        /// 加载本地化资源
        /// </summary>
        IList<LanguageModel> Load();

        /// <summary>
        /// 加载选定的本地化资源
        /// </summary>
        /// <param name="config">语言文化</param>
        /// <returns></returns>
        IList<Localzation> LoadList(string config = "");

        /// <summary>
        /// 新增资源
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="Value">本地化值</param>
        /// <param name="config">资源文件名</param>
        void Insert(string key,string Value,string config);

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="key"></param>
        /// <param name="Value"></param>
        /// <param name="config"></param>
        void Update(string key, string Value, string config);

        /// <summary>
        /// 根据资源名获取资源信息
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        string Resource(string key);

        /// <summary>
        /// 删除本地化资源某一项
        /// </summary>
        /// <param name="key"></param>
        /// <param name="config"></param>
        void Delete(string key, string config);

        /// <summary>
        /// 清空资源
        /// </summary>
        /// <param name="config"></param>
        void Delete(string config);
    }

实现类LocalizationSource如下:


    public class LocalizationSource : ILocalizationSource
    {
        /// <summary>
        /// 默认名称
        /// </summary>
        public const string DefaultConfig = "default.xml";
        /// <summary>
        /// 默认路径
        /// </summary>
        public const string ConfigPath = "Localization/Resource";

        private readonly ICacheManager _cacheManager;

        public LocalizationSource(ICacheManager cacheManager)
        {
            this._cacheManager = cacheManager;
        }

        #region 

        private IList<Localzation> FormatLocalzation(XmlNodeList nodes, string culture)
        {
            string key = string.Format("Localzation.{0}.List", culture);
            return _cacheManager.Get(key, () =>
            {
                if (nodes == null)
                    return null;
                var list = new List<Localzation>();
                for (int i = 0; i < nodes.Count; i++)
                {
                    var model = new Localzation
                    {
                        Key = nodes[i].Attributes["name"].Value,
                        Value = nodes[i].Attributes["value"].Value,
                    };
                    list.Add(model);
                }
                return list;
            });
        }


        #endregion

        #region method
        public void Delete(string config)
        {
            throw new NotImplementedException();
        }

        public void Delete(string key, string config)
        {
            throw new NotImplementedException();
        }

        public void Insert(string key, string Value, string config)
        {
            DirectoryInfo dinfo = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigPath));
            var resources = dinfo.GetFiles("*.xml");
            foreach (var r in resources)
            {
                try
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(r.FullName);
                    var culture = doc.LastChild.Attributes["culture"].Value;
                    if (culture == config)
                    {
                        var parent = doc.SelectSingleNode("localizationDictionary");
                        XmlElement newNode = doc.CreateElement("text");
                        newNode.SetAttribute("name", key);
                        newNode.SetAttribute("value", Value);
                        parent.AppendChild(newNode);
                        doc.Save(r.FullName);

                        string cacheKey = string.Format("Localzation.{0}.List", culture);
                        _cacheManager.Remove(cacheKey);
                        return;
                    }
                }
                catch
                {
                    continue;
                }
            }

        }

        public IList<LanguageModel> Load()
        {
            DirectoryInfo dinfo = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigPath));
            var resources = dinfo.GetFiles("*.xml");
            var list = new List<LanguageModel>();
            foreach (var r in resources)
            {
                try
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(r.FullName);
                    var culture = doc.LastChild.Attributes["culture"].Value;
                    CultureInfo c = new CultureInfo(culture);
                    var nodes = doc.SelectNodes("localizationDictionary/text");
                    var lang = new LanguageModel
                    {
                        Name = c.DisplayName,
                        Config = r.Name,
                        Culture = culture,
                        IsDefault = Convert.ToBoolean(doc.LastChild.Attributes["default"].Value),
                        Localzations = FormatLocalzation(nodes, culture)
                    };
                    list.Add(lang);
                }
                catch {
                    continue;
                }
            }
            return list;
        }


        public void Update(string key, string Value, string config)
        {
            throw new NotImplementedException();
        }

        public string Resource(string key)
        {
            DirectoryInfo dinfo = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigPath));
            var resources = dinfo.GetFiles("*.xml");
            var langs = new List<LanguageModel>();
            foreach (var r in resources)
            {
                try
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(r.FullName);
                    var culture = doc.LastChild.Attributes["culture"].Value;
                    if (culture == EngineContext.Culture)
                    {
                        var nodes = doc.SelectNodes("localizationDictionary/text");
                        var list = FormatLocalzation(nodes, culture);
                        return list.FirstOrDefault(x => x.Key == key).Value;
                    }

                }
                catch
                {
                    continue;
                }
            }
            return string.Format("[{0}]", key);
        }

        public IList<Localzation> LoadList(string config = "")
        {
            DirectoryInfo dinfo = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigPath));
            var resources = dinfo.GetFiles("*.xml");
            var langs = new List<LanguageModel>();
            foreach (var r in resources)
            {
                try
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(r.FullName);
                    var culture = doc.LastChild.Attributes["culture"].Value;
                    if (culture == config)
                    {
                        var nodes = doc.SelectNodes("localizationDictionary/text");
                        return FormatLocalzation(nodes, culture);
                    }

                }
                catch
                {
                    continue;
                }

            }
            return null;
        }
        #endregion
    }

Resource里面是什么?如下图!
这是Resource文件的列表
列表文件
资源文件格式
资源格式

3、重写Razor,在View视图文件夹增加类WebViewPage

public abstract class WebViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel>
    {
        private ILocalizationSource _localizationSource;
        protected string gridPageSizes = "20,40,60";
        protected int defaultGridPageSize = 20;

        protected virtual string L(string resource)
        {
            if (_localizationSource == null)
                return resource;
            return _localizationSource.Resource(resource);

        }

        public override void InitHelpers()
        {
            base.InitHelpers();
            _localizationSource = EngineContext.Current.Resolve<ILocalizationSource>();
        }


    }

    public abstract class WebViewPage : WebViewPage<dynamic>
    {
    }

修改View文件夹下的web.config定位到该类上面
这里写图片描述

4、通过单例模式启动项目
这里写图片描述
我这里只把关键的代码贴出来,自己下载项目看吧EngineContext代码


    /// <summary>
    /// 驱动引擎(单例)
    /// </summary>
    public class EngineContext
    {
        /// <summary>
        /// 容器
        /// </summary>
        public static IContainer container { get; set; }
        /// <summary>
        /// 语言文化(修改当前项目的语言设置)
        /// </summary>
        public static string Culture { get; set; }

        #region Methods

        /// <summary>
        /// 启动项
        /// </summary>
        /// <param name="forceRecreate"></param>
        /// <returns></returns>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static IEngine Initialize(bool forceRecreate,string culture)
        {
            Culture = culture;
            if (Singleton<IEngine>.Instance == null || forceRecreate)
            {
                Singleton<IEngine>.Instance = new ContenxtEngine();

                Singleton<IEngine>.Instance.Initialize();
            }
            return Singleton<IEngine>.Instance;
        }

        public static void Replace(IEngine engine)
        {
            Singleton<IEngine>.Instance = engine;
        }

        #endregion

        #region Properties

        /// <summary>
        /// 单例模式下的驱动器
        /// </summary>
        public static IEngine Current
        {
            get
            {
                if (Singleton<IEngine>.Instance == null)
                {
                    Initialize(false, "zh-CN");
                }
                return Singleton<IEngine>.Instance;
            }
        }

        #endregion
    }

映射服务IDependencyRegistrar和DependencyRegistrar实现类(如果项目较多,可以多个实现,IEngine实现类有注解)首先是注解方法ContenxtEngine的注册:


        /// <summary>
        /// 注册映射
        /// </summary>
        protected virtual void RegisterDependencies()
        {
            var builder = new ContainerBuilder();
            var container = builder.Build();
            this._containerManager = new ContainerManager(container);


            //register dependencies provided by other assemblies
            builder = new ContainerBuilder();
            var drTypes = GetType(typeof(IDependencyRegistrar));
            var drInstances = new List<IDependencyRegistrar>();
            foreach (var drType in drTypes)
                drInstances.Add((IDependencyRegistrar)Activator.CreateInstance(drType));
            //sort
            drInstances = drInstances.AsQueryable().OrderBy(t => t.Order).ToList();
            foreach (var dependencyRegistrar in drInstances)
                dependencyRegistrar.Register(builder);
            builder.Update(container);

            //set dependency resolver
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        }

注入类的实现DependencyRegistrar

/// <summary>
    /// 服务注入
    /// </summary>
    public class DependencyRegistrar : IDependencyRegistrar
    {
        public int Order
        {
            get
            {
                return 0;
            }
        }

        public void Register(ContainerBuilder builder)
        {
            builder.RegisterType<MemoryCacheManager>().As<ICacheManager>();
            builder.RegisterType<LocalizationSource>().As<ILocalizationSource>();
            //注册控制器
            builder.RegisterControllers(Assembly.GetExecutingAssembly());
        }
    }

最后就是控制器了


    public class ResourceController : Controller
    {
        private const string RESCOURCE_KEY = "solution.resource.list.all";

        private readonly ILocalizationSource _localizationSource;

        public ResourceController(ILocalizationSource localizationSource)
        {
            this._localizationSource = localizationSource;
        }

        public ActionResult List()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Data(DataSourceRequest command)
        {
            var list = _localizationSource.Load().Skip(command.Page - 1).Take(command.Take);

            var data = new DataSourceResult
            {
                Data = list,
                Total = list.Count()
            };
            return Json(data);
        }

        [HttpPost]
        public ActionResult List(int pageIndex = 0,int pageSize = int.MaxValue )
        {
            return View();
        }

        public ActionResult Edit(string config)
        {
            ViewBag.Config = config;
            return View();
        }

        #region resources
        [HttpPost]
        public ActionResult Resources(DataSourceRequest command, string config)
        {
            var list = _localizationSource.LoadList(config).Skip(command.Page - 1).Take(command.PageSize);

            var data = new DataSourceResult
            {
                Data = list,
                Total = list.Count()
            };
            return Json(data);
        }

        [HttpPost]
        public ActionResult ResourceAdd(string config, [Bind(Exclude = "config")] LanguageResourceModel model)
        {

            if (model.Key != null)
                model.Key = model.Key.Trim();
            if (model.Value != null)
                model.Value = model.Value.Trim();

            if (!ModelState.IsValid)
            {
                return Json(new DataSourceResult { Errors = ModelState.Where(entry => entry.Value.Errors.Any()) });
            }

            var list = _localizationSource.LoadList(config);
            if (list.FirstOrDefault(r => r.Key == model.Key) == null)
            {
                _localizationSource.Insert(model.Key, model.Value, config);
            }

            return Json(null);
        }

        [HttpPost]
        public ActionResult ResourceDelete(string key,string culture)
        {
            _localizationSource.Delete(key, culture);
            return Json(null);
        }

        #endregion
    }

主要说明下缓存的使用,我是在服务层里面使用的也就是LocalizationSource里面的FormatLocalzation方法,通过格式化key来获取内容如下:

private IList<Localzation> FormatLocalzation(XmlNodeList nodes, string culture)
        {
            string key = string.Format("Localzation.{0}.List", culture);
            return _cacheManager.Get(key, () =>
            {
                if (nodes == null)
                    return null;
                var list = new List<Localzation>();
                for (int i = 0; i < nodes.Count; i++)
                {
                    var model = new Localzation
                    {
                        Key = nodes[i].Attributes["name"].Value,
                        Value = nodes[i].Attributes["value"].Value,
                    };
                    list.Add(model);
                }
                return list;
            });
        }

试图部分我没有上传,去项目看吧,我用的Kendoui实现的web。本地化如何用呢?在的View视图中直接使用@L(“Resource”)就可以实现。因为我重写了Razor,增加了L方法,就像下面一样:
这里写图片描述

更多的信息请下载项目进行观看,项目下载地址:
http://download.csdn.net/detail/hb12417058/9715000

欢迎大家关注我的公众号!

这里写图片描述
扫一扫更多内容关注!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值