一、概述
有些功能在单个项目或多个项目被重复使用,比如:附件,同一个系统中的多个模块都可能使用到,不同项目也有需要。再比如:有无限级分类的树形功能,区域、产品分类、数据字典等。最简单粗暴的办法是直接复制代码,最后本来是同一个功能被复制了多份,而且可能最后都被各自修改得面目全非。
理想的办法是将这些通用功能封装起来,通过迭代升级版本,不同项目都可以引用他们,封装的时候留出扩展点方便每个项目的个性化需求
nuget中搜索bxjg可以找到已发布的模块,源码后续会放github上,猴急的你可以私我
本篇讲解如何使用,下篇讲如何通过abp提供的模块化能力实现一个通用树模块
注:ASP.NET Boilerplate简称abp,是个啥请百个度
二、如何使用
为了各位有个直观感受,我们来看看如何使用模块,后续再讲如何开发它。
2.1、基本使用
1、通过nuget安装通用树模块(最好是所有项目都安装 解决方案 -> 右键 管理解决方案的包 一次安装)
Install-Package BXJG.GeneralTree -Version 1.0.1
2、配置DbContext
public class ABPDbContext : AbpZeroDbContext<Tenant, Role, User>{ //其它配置 public virtual DbSet<GeneralTreeEntity> GeneralTrees { get; set; }
3、开启动动态webApi代理生成
public class ABPWebApiModule : AbpModule { public override void Initialize() { //other.. Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder .ForAll<IApplicationService>(typeof(GeneralTreeModule).Assembly, "gt/gt") .Build();
4、数据库迁移
add-migration addGeneralTree
update-database
此时编译调试,如果你有swaggerUI的话,应该可以看得到生成的动态webapi了
5、配置权限,在core项目的AuthorizationProvider中
public class ABPAuthorizationProvider : AuthorizationProvider{ GeneralTreeModuleConfig cfg;//注入模块的配置对象 public ABPAuthorizationProvider(GeneralTreeModuleConfig cfg) { this.cfg = cfg; } public override void SetPermissions(IPermissionDefinitionContext context){ //其它权限的配置 cfg.InitPermission(baseInfo);//通用字典权限的配置
6、配置菜单,配置方式跟权限配置类似。在web项目中的NavigationProvider
public class ABPNavigationProvider : NavigationProvider{ GeneralTreeModuleConfig cfg; public ABPNavigationProvider(GeneralTreeModuleConfig cfg){ this.cfg = cfg; } public override void SetNavigation(INavigationProviderContext context){ //其它菜单配置 var sjzd = cfg.InitNav(jczl); sjzd.Icon = "shuju"; sjzd.Url = "/baseinfo/generalTree/index.html";
此时你已经可用在项目中使用这个通用的数据字典模块了
2.2、扩展通用字典实现“区域”功能
1、定义实体,继承模块提供的抽象类
[Table("ABPAdministratives")] public class AdministrativeEntity : GeneralTreeEntity<AdministrativeEntity>{ /// <summary> /// 行政区域级别 /// </summary> public XZQ Level { get; set; } }
2、配置DbContext
public class ABPDbContext : AbpZeroDbContext<Tenant, Role, User>{ //其它配置 public virtual DbSet<AdministrativeEntity> Administratives { get; set; }
3、定义领域服务类
public class AdministrativeManager : GeneralTreeManager<AdministrativeEntity>{ public AdministrativeManager(IRepository<AdministrativeEntity, long> repository) : base(repository){ } }
4、按abp常规套路实现Application中的接口和dto,偷个懒,截个图
[AutoMapFrom(typeof(AdministrativeEntity))] public class AdministrativeDto : GeneralTreeGetTreeNodeBaseDto<AdministrativeDto> { public XZQ Level { get; set; } public string LevelText { get; set; } }
[AutoMapTo(typeof(AdministrativeEntity))] public class EditAdministrativetDto: GeneralTreeNodeEditBaseDto{ [Range(0, 3)] public int Level { get; set; } } public interface IAdministrativeAppService : IGeneralTreeAppServiceBase<AdministrativeDto,EditAdministrativetDto> {} public class AdministrativeAppService : GeneralTreeAppServiceBase<AdministrativeEntity, AdministrativeDto, EditAdministrativetDto>, IAdministrativeAppService{ public AdministrativeAppService( IRepository<AdministrativeEntity, long> repository, AdministrativeManager organizationUnitManager) : base(repository, organizationUnitManager, PermissionNames.AdministratorBaseInfoAdministrativeAdd, PermissionNames.AdministratorBaseInfoAdministrativeUpdate, PermissionNames.AdministratorBaseInfoAdministrativeDelete, PermissionNames.AdministratorBaseInfoAdministrative, "Nationwide", "Administrative") {} protected override void OnGetAllListItem(AdministrativeEntity entity, AdministrativeDto dto){ dto.LevelText = base.LocalizationSource.GetEnum(entity.Level); } protected override void OnGetForSelectItem(AdministrativeEntity entity, GeneralTreeNodeDto node){ node.attributes.Level = entity.Level; node.attributes.LevelText = base.LocalizationSource.GetEnum(entity.Level); }
三、总结
本篇只讲了使用,下篇会详细分析如何用abp实现模块化