首先我们需要的资源需要列一下:
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里面是什么?如下图!
列表文件
资源格式
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
欢迎大家关注我的公众号!
扫一扫更多内容关注!