面向介面程式設計實踐之aspnetcoreapi的抽象

星仔007發表於2023-04-18

最為一名越過菜鳥之後的開發,需要做介面開發。下面做一個純粹的介面程式設計的例項demo,僅僅是一個webapi介面的抽象。

下面是程式碼介面,AbsEFWork是webapi,BaseEntityFramework是一個介面庫。

先介紹一下webapi的實現,程式碼是從底層往上層寫的,閱讀程式碼的習慣應該是自上向下。

 public class ProductController : CustomController<Product>
    {
        public ProductController(IEFCoreService<Product> efCoreService) : base(efCoreService)
        {
        }
    }

控制器程式碼很簡單的實現了CustomController,資料載體是Product。

using BaseEntityFramework.Implementations;
using BaseEntityFramework.Implementations.Entitys;
using BaseEntityFramework.IService;
using Microsoft.EntityFrameworkCore;

namespace BaseEntityFramework
{
    public class Program
    {
        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 at https://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 class Product: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; }
    }
using BaseEntityFramework.Implementations.Entitys;
using Microsoft.EntityFrameworkCore;

namespace BaseEntityFramework.Implementations
{
    public class ProductDbContext:DbContext
    {
        public ProductDbContext(DbContextOptions<ProductDbContext> dbContextOptions):base(dbContextOptions)
        {

        } 
        public DbSet<Product> Products { get; set; }
    }
}

檢視上面的控制器程式碼,有注入IEFCoreService<Product>的業務程式碼,對於介面肯定是需要一個實現,這裡可以再次封裝一個抽象的基類來(溫馨提示:重複的程式碼,必須最佳化),我這裡暫時沒做處理。

using BaseEntityFramework.Implementations.Entitys;
using BaseEntityFramework.IService;
using BaseEntityFramework.Models;
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;

namespace BaseEntityFramework.Implementations
{
    public class EFCoreProductService : IEFCoreService<Product>
    {
        private readonly ProductDbContext _dbContext;
        public EFCoreProductService(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 new NotImplementedException();
        }

        public async Task<IEnumerable<Product>> GetAll()
        {
            var result =await _dbContext.Products.ToListAsync();
            return result;
        }

        public Task<Product> GetEntity(Expression<Func<Product, bool>> expression)
        {
            throw new NotImplementedException();
        }

        public async Task<IReadOnlyCollection<Product>> GetList(Expression<Func<Product, bool>> expression)
        {
            var result = await _dbContext.Products.Where(expression).ToListAsync();
            return result.AsReadOnly();
        }

        public Task<PageResult<Product>> GetPageResult<Req>(PageInput<Req> pagInput) where Req : new()
        {
            throw new NotImplementedException();
        }

        public Task<bool> Update(Product entity)
        {
            throw new NotImplementedException();
        }
    }
}

上面的程式碼很簡單易懂,最大的好處就是可以複用。實體類和 dbcontext越多這個簡簡單單的結構就越是有用。

 

BaseEntityFramework的核心邏輯就是把業務程式碼做了抽象,做了一個統一的模板,不管 是從那方便說都只有好處。而且作為開發只關心自己的業務程式碼這一塊。

 public interface IEFCoreService<T> where T: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,專案中需要做框架的話這或許是一個開始,需要做的遠遠不止這些。

原始碼:

liuzhixin405/AbsEFWork (github.com)

 

相關文章