DDD开发框架ABP之本地化资源的数据库存储扩展
2015-10-05 17:16
323 查看
在上一篇《DDD开发框架ABP之本地化/多语言支持》中,我们知道,ABP开发框架中本地化资源存储可以采用XML文件,RESX资源文件,也提供了其他自定义的存储方式的扩展接口。ABP框架默认实现了前面两种方式,而数据库存储方式则需要自己扩展,大概是因为数据库存储涉及到了实体和仓储等方面的具体内容,不适合放在基本框架里面。
以数据库的方式存储本地化资源,一个最明显的好处就是方便修改,尤其是对于基于数据库的应用系统而言,可以提供统一的维护界面。接下来我们就来一步步地实现将本地化资源存储在数据库中。
为了存储资源,我们需要建立一个实体:
其中Culture属性为语言代码,比如en, zh-TW, zh-CN等。Name属性为名称,Value属性为对应的文本。基类Entity是ABP框架提供的通用领域实体类,默认具有整型Id,且实现了IEntity接口。
其中IRepository<DBLocalization>以构造函数方式注入。
Name:资源名称,
Initialize():初始化方法,注册时被ABP调用
string GetString(string name) 根据名称取得文本
IReadOnlyList<LocalizedString> GetAllStrings() 取得当前语言的全部字典清单
ABP已经有三个实现了ILocalizationSource接口的类:NullLocalizationSource、ResourceFileLocalizationSource 和 DictionaryBasedLocalizationSource。
把资源文本存储于数据库中,每次取得文本时都访问数据库取得数据,但基于性能的考虑,显然将资源文本提前在初始化时一次性加载到内存,应该是更好地方式。由于DictionaryBasedLocalizationSource已经实现了内存字典的通用方法,我们不太需要再另外写一个DBLocalizationSource。查看DictionaryBasedLocalizationSource代码,可以看到其构造函数需要传入一个ILocalizationDictionaryProvider的实例,这个实例用于取得本地化字典的详细内容。
接下来我们建立一个类实现ILocalizationDictionaryProvider接口:
该类实现了接口的GetDictionaries方法,取得字典对象DBLocalizationDictionary。方法首先利用依赖注入容器自动得到一个IDBLocalizationManager的实例。
下面是DBLocalizationDictionary字典类的实现代码:
到这里,将本地化资源存储在数据库中就基本上已经全部实现,剩下的就是开发界面对本地化资源进行增删改查的维护了。
以数据库的方式存储本地化资源,一个最明显的好处就是方便修改,尤其是对于基于数据库的应用系统而言,可以提供统一的维护界面。接下来我们就来一步步地实现将本地化资源存储在数据库中。
第一步 建立实体
如果以XML存储资源,我们需要建立XML的资源文件,支持多少种语言则需要建立多少个资源文件。那么以数据库存储资源文本,自然也需要建立实体,然后实现实体的读操作。为了存储资源,我们需要建立一个实体:
public class DBLocalization : Entity { [Required] [StringLength(10)] public virtual string Culture { get; set; } [Required] [StringLength(50)] public virtual string Name { get; set; } [Required] public virtual string Value { get; set; } }
其中Culture属性为语言代码,比如en, zh-TW, zh-CN等。Name属性为名称,Value属性为对应的文本。基类Entity是ABP框架提供的通用领域实体类,默认具有整型Id,且实现了IEntity接口。
第二步 建立领域服务
领域服务提供对实体的数据操作,比如取得语言种类和语言字典。public class DBLocalizationManager : DomainService { private readonly IRepository<DBLocalization> _localizationRepository; public DBLocalizationManager(IRepository<DBLocalization> localizationRepository) { _localizationRepository = localizationRepository; } public List<CultureInfo> GetCultures() { return _localizationRepository.GetAllList() .Select(p => new CultureInfo(p.Culture)) .Distinct() .ToList<CultureInfo>(); } public List<DBLocalization> GetDictionary() { return _localizationRepository.GetAllList(); } }
其中IRepository<DBLocalization>以构造函数方式注入。
第三步 实现本地化资源接口(ILocalizationSource)
ILocalizationSource是本地化框架的核心接口,接口方法包括:Name:资源名称,
Initialize():初始化方法,注册时被ABP调用
string GetString(string name) 根据名称取得文本
IReadOnlyList<LocalizedString> GetAllStrings() 取得当前语言的全部字典清单
ABP已经有三个实现了ILocalizationSource接口的类:NullLocalizationSource、ResourceFileLocalizationSource 和 DictionaryBasedLocalizationSource。
把资源文本存储于数据库中,每次取得文本时都访问数据库取得数据,但基于性能的考虑,显然将资源文本提前在初始化时一次性加载到内存,应该是更好地方式。由于DictionaryBasedLocalizationSource已经实现了内存字典的通用方法,我们不太需要再另外写一个DBLocalizationSource。查看DictionaryBasedLocalizationSource代码,可以看到其构造函数需要传入一个ILocalizationDictionaryProvider的实例,这个实例用于取得本地化字典的详细内容。
接下来我们建立一个类实现ILocalizationDictionaryProvider接口:
public class DBLocalizationDictionaryProvider : ILocalizationDictionaryProvider { private DBLocalizationManager _dbLocalizationManager; public IEnumerable<LocalizationDictionaryInfo> GetDictionaries(string sourceName) { if (_dbLocalizationManager == null) { if (IocManager.Instance.IsRegistered<DBLocalizationManager>()) { _dbLocalizationManager = IocManager.Instance.Resolve<DBLocalizationManager>(); } } var dictionaries = new List<LocalizationDictionaryInfo>(); foreach (var culture in _dbLocalizationManager.GetCultures()) { dictionaries.Add( new LocalizationDictionaryInfo( DBLocalizationDictionary.Build(culture.Name, _dbLocalizationManager.GetDictionary()) , isDefault: culture.Name == ZeroConsts.DefaultLanguage ) ); } return dictionaries; } }
该类实现了接口的GetDictionaries方法,取得字典对象DBLocalizationDictionary。方法首先利用依赖注入容器自动得到一个IDBLocalizationManager的实例。
下面是DBLocalizationDictionary字典类的实现代码:
public class DBLocalizationDictionary : LocalizationDictionary { private DBLocalizationDictionary(CultureInfo cultureInfo) : base(cultureInfo) { } public static DBLocalizationDictionary Build(string cultureName, List<DBLocalization> dictList) { try { var dictionary = new DBLocalizationDictionary(new CultureInfo(cultureName)); var dublicateNames = new List<string>(); if (dictList != null && dictList.Count>0) { foreach (DBLocalization item in dictList.FindAll(c => c.Culture == cultureName)) { if (string.IsNullOrEmpty(item.Name)) { throw new AbpException("name of a dictionary is empty in given data."); } if (dictionary.Contains(item.Name)) { dublicateNames.Add(item.Name); } dictionary[item.Name] = item.Value.NormalizeLineEndings(); } } if (dublicateNames.Count > 0) { throw new AbpException("A dictionary can not contain same key twice. There are some duplicated names: " + dublicateNames.JoinAsString(", ")); } return dictionary; } catch (Exception ex) { throw new AbpException("Invalid localization data format! ", ex); } } }
第四步 注册资源
在需要使用多语言本地化的模块,我们可以在模块的PreInitialize方法中,注册资源。一个模块可以在Configuration.Localization.Sources 集合中添加多个资源,只要实现了ILocalizationSource接口即可。public override void PreInitialize() { Configuration.Localization.Sources.Add( new DictionaryBasedLocalizationSource("Zero", new DBLocalizationDictionaryProvider())); }
到这里,将本地化资源存储在数据库中就基本上已经全部实现,剩下的就是开发界面对本地化资源进行增删改查的维护了。
相关文章推荐
- MySQL数据库多种优化方案
- Oracle存储过程实例
- mysql的索引
- HTML5权威指南--Web Storage,本地数据库,本地缓存API,Web Sockets API,Geolocation API(简要学习笔记二)
- Oracle触发器实例
- MySQL备份与恢复
- Redis源码阅读-sds字符串源码阅读
- 完整java开发中JDBC连接数据库代码和步骤
- MySQL命令大全及查询语句
- (转)完整java开发中JDBC连接数据库代码和步骤
- 数据库性能优化的方法(转)
- hibernate.cfg.xml配置(Oracle+c3p0)
- mysql 卸载-安装-主从集群
- C# : ADO 读取 SQLite
- C#窗体操作SQL Server存储大文件方法分享
- 如何通过PL/SQL Developer备份恢复oracle数据
- mysql5.6通过mysqldump自动备份
- Redis源码阅读-Dict哈希字典
- oracle5
- 使用SQL SERVER2005的时候常常遇到中文字符为乱码的情况