DDD开发框架ABP之本地化资源的数据库存储扩展

在上一篇《DDD开发框架ABP之本地化/多语言支持》中,我们知道,ABP开发框架中本地化资源存储可以采用XML文件,RESX资源文件,也提供了其他自定义的存储方式的扩展接口。ABP框架默认实现了前面两种方式,而数据库存储方式则需要自己扩展,大概是因为数据库存储涉及到了实体和仓储等方面的具体内容,不适合放在基本框架里面。

以数据库的方式存储本地化资源,一个最明显的好处就是方便修改,尤其是对于基于数据库的应用系统而言,可以提供统一的维护界面。接下来我们就来一步步地实现将本地化资源存储在数据库中。

第一步 建立实体

如果以XML存储资源,我们需要建立XML的资源文件,支持多少种语言则需要建立多少个资源文件。那么以数据库存储资源文本,自然也需要建立实体,然后实现实体的读操作。

为了存储资源,我们需要建立一个实体:

 1 public class DBLocalization : Entity
 2 {
 3     [Required]
 4     [StringLength(10)]
 5     public virtual string Culture { get; set; }
 6     [Required]
 7     [StringLength(50)]
 8     public virtual string Name { get; set; }
 9     [Required]
10     public virtual string Value { get; set; }
11 }

其中Culture属性为语言代码,比如en, zh-TW, zh-CN等。Name属性为名称,Value属性为对应的文本。基类Entity是ABP框架提供的通用领域实体类,默认具有整型Id,且实现了IEntity接口。

第二步 建立领域服务

领域服务提供对实体的数据操作,比如取得语言种类和语言字典。

 1 public class DBLocalizationManager : DomainService
 2 {
 3     private readonly IRepository<DBLocalization> _localizationRepository;
 4     public DBLocalizationManager(IRepository<DBLocalization> localizationRepository)
 5     {
 6         _localizationRepository = localizationRepository;
 7     }
 8     public List<CultureInfo> GetCultures()
 9     {
10         return _localizationRepository.GetAllList()
11         .Select(p => new CultureInfo(p.Culture))
12         .Distinct()
13         .ToList<CultureInfo>();
14     }
15     public List<DBLocalization> GetDictionary()
16     {
17         return _localizationRepository.GetAllList();
18     }
19 }

其中IRepository<DBLocalization>以构造函数方式注入。

第三步 实现本地化资源接口(ILocalizationSource)

ILocalizationSource是本地化框架的核心接口,接口方法包括:

Name:资源名称,
      Initialize():初始化方法,注册时被ABP调用
      string GetString(string name) 根据名称取得文本
      IReadOnlyList<LocalizedString> GetAllStrings() 取得当前语言的全部字典清单

ABP已经有三个实现了ILocalizationSource接口的类:NullLocalizationSource、ResourceFileLocalizationSource 和 DictionaryBasedLocalizationSource。

把资源文本存储于数据库中,每次取得文本时都访问数据库取得数据,但基于性能的考虑,显然将资源文本提前在初始化时一次性加载到内存,应该是更好地方式。由于DictionaryBasedLocalizationSource已经实现了内存字典的通用方法,我们不太需要再另外写一个DBLocalizationSource。查看DictionaryBasedLocalizationSource代码,可以看到其构造函数需要传入一个ILocalizationDictionaryProvider的实例,这个实例用于取得本地化字典的详细内容。
      接下来我们建立一个类实现ILocalizationDictionaryProvider接口:

 1 public class DBLocalizationDictionaryProvider : ILocalizationDictionaryProvider
 2 {
 3     private DBLocalizationManager _dbLocalizationManager;
 4     public IEnumerable<LocalizationDictionaryInfo> GetDictionaries(string sourceName)
 5     {
 6         if (_dbLocalizationManager == null)
 7         {
 8             if (IocManager.Instance.IsRegistered<DBLocalizationManager>())
 9             {
10             _dbLocalizationManager = IocManager.Instance.Resolve<DBLocalizationManager>();
11             }
12         }
13         var dictionaries = new List<LocalizationDictionaryInfo>();
14         foreach (var culture in _dbLocalizationManager.GetCultures())
15         {
16             dictionaries.Add(
17                 new LocalizationDictionaryInfo(
18                     DBLocalizationDictionary.Build(culture.Name,
19                     _dbLocalizationManager.GetDictionary()) ,
20                     isDefault: culture.Name == ZeroConsts.DefaultLanguage
21                 )
22             );
23         }
24         return dictionaries;
25     }
26 }

该类实现了接口的GetDictionaries方法,取得字典对象DBLocalizationDictionary。方法首先利用依赖注入容器自动得到一个IDBLocalizationManager的实例。

下面是DBLocalizationDictionary字典类的实现代码:

 1 public class DBLocalizationDictionary : LocalizationDictionary
 2 {
 3     private DBLocalizationDictionary(CultureInfo cultureInfo)
 4         : base(cultureInfo)
 5     {
 6     }
 7     public static DBLocalizationDictionary Build(string cultureName, List<DBLocalization> dictList)
 8     {
 9         try
10         {
11             var dictionary = new DBLocalizationDictionary(new CultureInfo(cultureName));
12             var dublicateNames = new List<string>();
13             if (dictList != null && dictList.Count>0)
14             {
15                 foreach (DBLocalization item in dictList.FindAll(c => c.Culture == cultureName))
16                 {
17                     if (string.IsNullOrEmpty(item.Name))
18                     {
19                         throw new AbpException("name of a dictionary is empty in given data.");
20                     }
21                     if (dictionary.Contains(item.Name))
22                     {
23                         dublicateNames.Add(item.Name);
24                     }
25                     dictionary[item.Name] = item.Value.NormalizeLineEndings();
26                 }
27             }
28             if (dublicateNames.Count > 0)
29             {
30                 throw new AbpException("A dictionary can not contain same key twice. There are some duplicated names: " + dublicateNames.JoinAsString(", "));
31             }
32             return dictionary;
33         }
34         catch (Exception ex)
35         {
36             throw new AbpException("Invalid localization data format! ", ex);
37         }
38     }
39 }

第四步 注册资源

在需要使用多语言本地化的模块,我们可以在模块的PreInitialize方法中,注册资源。一个模块可以在Configuration.Localization.Sources 集合中添加多个资源,只要实现了ILocalizationSource接口即可。

1 public override void PreInitialize()
2 {
3     Configuration.Localization.Sources.Add(
4         new DictionaryBasedLocalizationSource("Zero", new DBLocalizationDictionaryProvider()));
5 }

  到这里,将本地化资源存储在数据库中就基本上已经全部实现,剩下的就是开发界面对本地化资源进行增删改查的维护了。

时间: 2024-10-23 23:44:05

DDD开发框架ABP之本地化资源的数据库存储扩展的相关文章

DDD开发框架ABP之本地化/多语言支持

本地化(Localization)也就是多语言功能,借此用户能够选择他的母语或熟悉的语言来使用系统,这显然非常有利于软件系统推向国际化.一个应用程序的UI界面至少有一种语言,DDD开发框架ABP就提供了一个弹性的多语言框架,可以简化我们在多语言方面的开发时间.利用ABP完整实现多语言只需要简单地完成三个步骤:建立资源.配置资源以及使用资源. 一.建立资源 本地化的内容主要是文本字符串,ABP提供三种方式存储本地化资源的方式,分别是ASP.NET自带的资源文件.XML文件以及自定义的资源获取方式.

基于DDD的现代ASP.NET开发框架--ABP系列之2、ABP入门教程

点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之2.ABP入门教程 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://gith

基于DDD的现代ASP.NET开发框架--ABP系列之3、ABP分层架构

点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之3.ABP分层架构 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://github.com/aspnetboilerplate 前言 为了减少复杂性和提高代码的可重用性,采用分层架构是一种被广泛接受的技术.为了实现分层的体系结

基于DDD的现代ASP.NET开发框架--ABP系列之8、ABP日志管理

点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之8.ABP日志管理 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://github.com/aspnetboilerplate 本文由东莞-天道提供翻译 Server side(服务器端) ASP.NET Boilerplat

基于DDD的现代ASP.NET开发框架--ABP系列之6、ABP依赖注入

点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之6.ABP依赖注入 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://github.com/aspnetboilerplate 本文由 上海-半冷 提供翻译 什么是依赖注入 如果你已经知道依赖注入的概念,构造函数和属性注入模式

基于DDD的现代ASP.NET开发框架--ABP系列之5、ABP启动配置

点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之5.ABP启动配置 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://github.com/aspnetboilerplate 本文由 东莞-天道 提供翻译 译者注:在看这一节的内容之前,建议大家先下载module-zero这

基于DDD的现代ASP.NET开发框架--ABP系列之7、ABP Session管理

点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之7.ABP Session管理 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://github.com/aspnetboilerplate 简介 如果一个应用程序需要登录,则它必须知道当前用户执行了什么操作.因此ASP.NET

基于DDD的现代ASP.NET开发框架--ABP系列之4、ABP模块系统

点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之4.ABP模块系统 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://github.com/aspnetboilerplate 本文由东莞-天道提供翻译 ABP模块系统简介 ABP框架提供了创建和组装模块的基础,一个模块能够依

基于Enterprise Library的Winform开发框架实现支持国产达梦数据库的扩展操作

由于一个客户朋友的需求,需要我的Winform开发框架支持国产达梦数据库的操作,这个数据库很早就听过,但是真正一般项目用的很少,一般在一些特殊的项目可能需要用到.由于我的Winform开发框架,是基于Enterprise Library的数据访问层的实现,因此增加一个数据库的支持很容易,本文介绍如何在框架层面上支持这种神秘的国产数据库-达梦数据库. 1.达梦数据库的简单介绍 达梦数据库管理系统是达梦公司推出的具有完全自主知识产权的高性能数据库管理系统,简称DM.达梦数据库管理系统的最新版本是7.