面向接口编程实践之aspnetcoreapi的抽象
最为一名越过菜鸟之后的开发,需要做接口开发。下面做一个纯粹的接口编程的实例demo,仅仅是一个webapi接口的抽象。
下面是代码接口,AbsEFWork是webapi,BaseEntityFramework是一个接口库。
先介绍一下webapi的实现,代码是从底层往上层写的,阅读代码的习惯应该是自上向下。
public class ProductController : CustomController<Product>{public ProductController(IEFCoreService<Product> efCoreService) : base(efCoreService)
{
}
}
控制器代码很简单的实现了CustomController,数据载体是Product。
usingBaseEntityFramework.Implementations;usingBaseEntityFramework.Implementations.Entitys;usingBaseEntityFramework.IService;usingMicrosoft.EntityFrameworkCore;namespaceBaseEntityFramework
{public classProgram
{public static void Main(string[] args)
{var builder =WebApplication.CreateBuilder(args);//Add services to the container. builder.Services.AddControllers();
builder.Services.AddDbContext<ProductDbContext>(options => options.UseInMemoryDatabase("memorydb"));//Learn more about configuring Swagger/OpenAPI athttps://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddScoped<IEFCoreService<Product>, EFCoreProductService>();var app =builder.Build();//Configure the HTTP request pipeline. if(app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
}
}
Program启动程序需要实现IEFCoreService的注入,以及ProductDbContext 的内存实现。
这样就可以启动一个swagger
对于product数据存储的具体实现,实体类product和dbcontext必须要自己去实现它。
public classProduct:IEntity
{
[Key]public int Id { get; set; }public string Name { get; set; }public string Description { get; set; }
[Column(TypeName= "decimal(28,16)")]public decimal Price { get; set; }
}
usingBaseEntityFramework.Implementations.Entitys;usingMicrosoft.EntityFrameworkCore;namespaceBaseEntityFramework.Implementations
{public classProductDbContext:DbContext
{public ProductDbContext(DbContextOptions<ProductDbContext> dbContextOptions):base(dbContextOptions)
{
}public DbSet<Product> Products { get; set; }
}
}
查看上面的控制器代码,有注入IEFCoreService<Product>的业务代码,对于接口肯定是需要一个实现,这里可以再次封装一个抽象的基类来(温馨提示:重复的代码,必须优化),我这里暂时没做处理。
usingBaseEntityFramework.Implementations.Entitys;usingBaseEntityFramework.IService;usingBaseEntityFramework.Models;usingMicrosoft.EntityFrameworkCore;usingSystem.Linq.Expressions;namespaceBaseEntityFramework.Implementations
{public class EFCoreProductService : IEFCoreService<Product>{private readonlyProductDbContext _dbContext;publicEFCoreProductService(ProductDbContext productDbContext)
{
_dbContext=productDbContext;
}public async Task<bool>Add(Product entity)
{
_dbContext.Products.Add(entity);var result = await_dbContext.SaveChangesAsync();return result != 0;
}public Task<bool>Delete(Product entity)
{throw newNotImplementedException();
}public async Task<IEnumerable<Product>>GetAll()
{var result =await_dbContext.Products.ToListAsync();returnresult;
}public Task<Product> GetEntity(Expression<Func<Product, bool>>expression)
{throw newNotImplementedException();
}public async Task<IReadOnlyCollection<Product>> GetList(Expression<Func<Product, bool>>expression)
{var result = await_dbContext.Products.Where(expression).ToListAsync();returnresult.AsReadOnly();
}public Task<PageResult<Product>> GetPageResult<Req>(PageInput<Req> pagInput) where Req : new()
{throw newNotImplementedException();
}public Task<bool>Update(Product entity)
{throw newNotImplementedException();
}
}
}
上面的代码很简单易懂,最大的好处就是可以复用。实体类和 dbcontext越多这个简简单单的结构就越是有用。
BaseEntityFramework的核心逻辑就是把业务代码做了抽象,做了一个统一的模板,不管 是从那方便说都只有好处。而且作为开发只关心自己的业务代码这一块。
public interface IEFCoreService<T> whereT:IEntity
{
Task<bool>Add(T entity) ;
Task<bool>Delete(T entity);
Task<bool>Update(T entity);
Task<IReadOnlyCollection<T>> GetList(Expression<Func<T,bool>>expression) ;
Task<PageResult<T>> GetPageResult<Req>(PageInput<Req> pagInput) where Req:new();
Task<T> GetEntity(Expression<Func<T, bool>>expression);
Task<IEnumerable<T>>GetAll();
}
以上的实例只是一个简单的demo,项目中需要做框架的话这或许是一个开始,需要做的远远不止这些。
源代码: