1、依赖注入:ABP使用并提供常规的DI基础结构。由于此类是一种应用程序服务,因此通常将其作为瞬态(根据请求创建)注册到DI容器。它可以简单地注入任何依赖项(例如:IRepository <Authorization.Tasks.Task>)。
2、存储库:ABP可以为每个实体创建默认存储库 。
3、自动映射:使用ABP的IObjectMapper的MapTo方法轻松地将属性从一个对象映射到另一个对象。
4、日志记录:在ABP框架中可以直接使用日志log4net,在MyABP.Web.Mvc中的Startup的ConfigureServices方法中可以修改成其他类型的日志
( options => options.IocManager.IocContainer.AddFacility<LoggingFacility>(f => f.UseAbpLog4Net().WithConfig("log4net.config")。
public class TaskAppService : MyABPAppServiceBase, ITaskAppService {//由于Abp框架要求使用依赖注入,这里的taskRepository和Logger 都是使用了依赖注入方式 private readonly IRepository<Authorization.Tasks.Task> _taskRepository;//定义仓储 public ILogger Logger { get; set; } public TaskAppService(IRepository<Authorization.Tasks.Task> taskRepository) { _taskRepository = taskRepository; Logger = NullLogger.Instance; } public async Task<ListResultDto<TaskListDto>> GetAll(GetAllTasksInput input) { var tasks = await _taskRepository .GetAll()//这里利用仓储查询数据 .Include(t => t.AssignedPerson) .WhereIf(input.State.HasValue, t => t.State == input.State.Value) .OrderByDescending(t => t.CreationTime) .ToListAsync(); return new ListResultDto<TaskListDto>( ObjectMapper.Map<List<TaskListDto>>(tasks)//自动映射 ); } public async Task Create(CreateTaskInput input) { var task = ObjectMapper.Map<Authorization.Tasks. Task>(input); await _taskRepository.InsertAsync(task);//利用仓储插入一条数据 Logger.Info("Creating a new task with description: " + input.Description);//使用日志 } }
5、自定义映射:一、定义接口IDtoMapping
using AutoMapper; namespace MyABP { /// <summary> /// 实现该接口以进行映射规则创建 /// </summary> internal interface IDtoMapping { void CreateMapping(IMapperConfigurationExpression mapperConfig); } }
二、定义一个类DtoMapping继承IDtoMapping,用来定于需要自定义的Dto创建映射类
using AutoMapper; using MyABP.Authorization.Tasks; using MyABP.Tasks.DTO; namespace MyABP { public class DtoMapping : IDtoMapping { public void CreateMapping(IMapperConfigurationExpression mapperConfig) { //自定义映射 var taskCacheDtoMapper = mapperConfig.CreateMap<Task, CreateTaskCache>(); taskCacheDtoMapper.ForMember(dto => dto.title, map => map.MapFrom(m => m.Title)); taskCacheDtoMapper.ForMember(dto => dto.description, map => map.MapFrom(m => m.Description)); taskCacheDtoMapper.ForMember(dto => dto.personId, map => map.MapFrom(m => m.AssignedPersonId)); var taskListDtoMapper = mapperConfig.CreateMap<Task, TaskListDto>(); taskListDtoMapper.ForMember(dto => dto.Id, map => map.MapFrom(m => m.Id)); taskListDtoMapper.ForMember(dto => dto.State, map => map.MapFrom(m => m.State)); } } }
三、在MyABPApplicationModule的Initialize方法中注册IDtoMapping依赖
//注册IDtoMapping IocManager.IocContainer.Register( Classes.FromAssembly(Assembly.GetExecutingAssembly()) .IncludeNonPublicTypes() .BasedOn<IDtoMapping>() .WithService.Self() .WithService.DefaultInterfaces() .LifestyleTransient() ); //解析依赖,并进行映射规则创建 Configuration.Modules.AbpAutoMapper().Configurators.Add(mapper => { var mappers = IocManager.IocContainer.ResolveAll<IDtoMapping>(); foreach (var dtomap in mappers) dtomap.CreateMapping(mapper); });
6、Cache:缓存(这里介绍的是缓存实体)
一、定义接口ITasksCache
using MyABP.Tasks.DTO; namespace MyABP.Application.Tasks { public interface ITasksCache: IEntityCache<CreateTaskCache> { } }
二、定义一个类TasksCache.cs来继承ITasksCache(其中Task和TaskCacheDto使用第5点中的自定义映射方式完成映射)
using Abp.Domain.Entities.Caching; using Abp.Domain.Repositories; using Abp.Runtime.Caching; using MyABP.Authorization.Tasks; using MyABP.Tasks.DTO; namespace MyABP.Application.Tasks { public class TasksCache : EntityCache<Task, CreateTaskCache>, ITasksCache, ITransientDependency { public TasksCache(ICacheManager cacheManager, IRepository<Task> repository) : base(cacheManager, repository) { } } }
三、读取缓存
private readonly ITasksCache _tasksCache;//cache public TaskAppService(IRepository<Authorization.Tasks.Task> taskRepository, ITasksCache tasksCache) { _taskRepository = taskRepository; Logger = NullLogger.Instance; _tasksCache = tasksCache; } public async void GetTitle(int id) { var title=_tasksCache[id].title; }
using Abp.Domain.Entities.Caching; using Abp.Domain.Repositories; using Abp.Runtime.Caching; using MyABP.Authorization.Tasks; using MyABP.Tasks.DTO; namespace MyABP.Application.Tasks { public class TasksCache : EntityCache<Task, CreateTaskCache>, ITasksCache, ITransientDependency { public TasksCache(ICacheManager cacheManager, IRepository<Task> repository) : base(cacheManager, repository) { } } }
using Abp.Domain.Entities.Caching; using Abp.Domain.Repositories; using Abp.Runtime.Caching; using MyABP.Authorization.Tasks; using MyABP.Tasks.DTO; namespace MyABP.Application.Tasks { public class TasksCache : EntityCache<Task, CreateTaskCache>, ITasksCache, ITransientDependency { public TasksCache(ICacheManager cacheManager, IRepository<Task> repository) : base(cacheManager, repository) { } } }
7、Session:获取当前用户、租户
public IAbpSession AbpSession { get; set; }//session private readonly ITasksCache _tasksCache;//cache public TaskAppService(IRepository<Authorization.Tasks.Task> taskRepository, ITasksCache tasksCache) { _taskRepository = taskRepository; Logger = NullLogger.Instance; AbpSession = NullAbpSession.Instance; _tasksCache = tasksCache; } public async void GetTitle(int id) { var userId = AbpSession.UserId; var title=_tasksCache[id].title; }
using MyABP.Tasks.DTO; namespace MyABP.Application.Tasks { public interface ITasksCache: IEntityCache<CreateTaskCache> { } }
- 授权:ABP可以声明性检查权限。如果当前用户没有“更新任务”权限或未登录,则它阻止访问UpdateTask方法。ABP不仅使用声明性属性,而且还具有其他授权方式。
- 验证:ABP自动检查输入是否为空。它还基于标准数据注释属性和自定义验证规则来验证输入的所有属性。如果请求无效,它将引发适当的验证异常并在客户端进行处理。
- 审核日志记录:用户,浏览器,IP地址,呼叫服务,方法,参数,呼叫时间,执行持续时间和其他一些信息会根据约定和配置自动为每个请求保存。
- 工作单元:在ABP中,默认情况下,每种应用程序服务方法都假定为工作单元。它会自动创建一个连接,并在方法开始时开始一个事务。如果该方法无例外地成功完成,则将提交事务并释放连接。即使此方法使用不同的存储库或方法,它们都将是原子的(事务性的)。提交事务后,将自动保存对实体的所有更改。我们甚至不需要调用上面所示的_repository.Update(task)方法。
- 异常处理:我们几乎不需要在Web应用程序上手动处理ABP中的异常。默认情况下,所有异常都会自动处理!如果发生异常,ABP会自动记录该异常并将正确的结果返回给客户端。例如,如果这是一个AJAX请求,它将向客户端返回一个JSON对象,指示发生错误。除非该示例中使用的是UserFriendlyException异常,否则它将向客户端隐藏实际的异常。它还了解并处理客户端的错误,并向用户显示适当的消息。
- 日志记录:如您所见,我们可以使用基类中定义的Logger对象编写日志。Log4Net默认情况下使用,但它是可更改和可配置的。
- 本地化:请注意,在引发异常时我们使用了“ L”方法?这样,它会根据当前用户的文化自动进行本地化。有关更多信息,请参见本地化文档。
- 自动映射:在最后一行,我们使用ABP的IObjectMapper的MapTo方法映射输入。属性到实体属性。它使用AutoMapper库执行映射。我们可以根据命名约定轻松地将属性从一个对象映射到另一个对象。
- 动态API层:实际上,TaskAppService是一个简单的类。通常,我们必须编写包装API控制器以将方法公开给JavaScript客户端,但是ABP在运行时会自动执行。这样,我们可以直接从客户端使用应用程序服务方法。
- 动态JavaScript AJAX代理:ABP创建代理方法,使调用应用程序服务方法就像在客户端上调用JavaScript方法一样简单。