文章目录
- 项目地址
- 五、Clean Architecture
- 5.1 user cage driven
- 5.1.1创建CoreBusiness
- 5.2 创建UseCases
- 5.2.1 创建CategoriesUseCases
- 1. 创建`VeiwCategoriesUseCase`获取所有Cagegory
- 5.2.2. 实现ICategoryRepository接口
- 3. 实现获取所有Category的方法
- 4. 实现获取一个Cagegory的方法
- 5. 实现编辑Category的方法
- 6. 实现获取删除Category的方法
- 5.2.3 创建ProductsUseCases
- 1. 创建一个AddProductUseCase
- 2. 使用快捷键生成IProductRepository接口
- 3. 通过快捷键生成接口对应的AddProduct方法
- 4. 通过同样的方式,将剩下的几个UseCase完成
- 5. 通过快捷键将UseCase 提取成为接口
- 5.3 创建Plugins
- 5.3.1 实现一个内存存储的plugin
- 5.4 使用IOC在Controllers里
- 5.4.1 将CategoriesUseCases里的实现抽离成为接口
- 5.4.2 在CategoriesContollers里使用
- 5.4.3 使用相同的方法将Categories相关的usecase抽离成为接口
项目地址
- 教程作者:
- 教程地址:
- 代码仓库地址:
- 所用到的框架和插件:
dbt
airflow
五、Clean Architecture
- usecase driven
- plugin based
5.1 user cage driven
5.1.1创建CoreBusiness
业务实体存放的类
- 创建一个class library,
CoreBusiness
- 将
Models
文件夹下的Categories.cs
和Products.cs
以及Transactions.cs
三个实体类,移动到CoreBusiness类库里,并修改他们的namespace
5.2 创建UseCases
- 创建
UseCases
类库
5.2.1 创建CategoriesUseCases
- 从功能出发,如果我们需要一个处理Categories相关的业务,需要对Categories数据表有哪些操作
- 查询出所有的Categories, ViewCategoriesUseCase.cs
- 查询单个Category的信息,ViewSelectedCategoryUseCase.cs
- 添加单个Category,AddCategoryUseCase.cs
- 编辑单个Category,EditCategoryUseCase.cs
- 删除单个Category,DeleteCategoryUseCase.cs
1. 创建VeiwCategoriesUseCase
获取所有Cagegory
- 在UseCases类库里,创建文件夹
CategoriesUseCases
文件夹 - 在该文件夹下添加
ViewCategoriesUseCase.cs
- ViewCategoriesUseCase.cs 只有一个公共的方法对外使用,因为他的功能显示Category的列表
- 添加对CoreBusiness的引用
- 创建一个返回所有Category的方法Excute()
public IEnumerable<Category> Excute()
{
}
- 使用构造方法,注入一个
ICategoryRepository
,这里这个接口还没有实现,只是我们知道我们需要用到这个接口提供的方法来获取我们想要的数据,这就是usecase driven的核心
namespace UseCases.CategoriesUseCases
{public class ViewCategoriesUseCase{private readonly ICategoryRepository _categoryRepository;public ViewCategoriesUseCase(ICategoryRepository categoryRepository){this._categoryRepository = categoryRepository;}public IEnumerable<Category> Excute(){//需要用到这个接口给我们提供的GetCategories方法获取数据return _categoryRepository.GetCategories();}}
}
- 至此,就完成了一个简单的Use Case Driven,在UseCases层,我们关心,接口哪里来,在哪里实现,只关心我需要这个接口以及接口能解决问题的方法,只是接口的使用者;
5.2.2. 实现ICategoryRepository接口
定义了与 Category 实体相关的操作,所有关于Category的操作都在这个接口上,供给plugins使用
1 . 在UseCases里创建文件夹DataStorePluginInterfaces
2. 创建ICategoryRepository.cs
using CoreBusiness;namespace UseCases.DataStorePluginInterfaces
{public interface ICategoryRepository{}
}
- 然后通过
CategoriesUseCases
里创建的方法,来逆向实现接口
3. 实现获取所有Category的方法
- 在
ViewCategoriesUseCase.cs
里实现GetCategories()
方法,该类只负责获取所有的Category列表,单一职责
using CoreBusiness;
using UseCases.DataStorePluginInterfaces;namespace UseCases.CategoriesUseCases
{public class ViewCategoriesUseCase{private readonly ICategoryRepository _categoryRepository;public ViewCategoriesUseCase(ICategoryRepository categoryRepository){this._categoryRepository = categoryRepository;}public IEnumerable<Category> Excute(){return _categoryRepository.GetCategories();}}
}
4. 实现获取一个Cagegory的方法
- 创建
ViewSelectedCategoryUseCase.cs
,该类只负责获取一个Cagegory
namespace UseCases.CategoriesUseCases
{public class ViewSelectedCategoryUseCase{private readonly ICategoryRepository _categoryRepository;public ViewSelectedCategoryUseCase(ICategoryRepository categoryRepository){this._categoryRepository = categoryRepository;}public Category Excute(int categoryId){return _categoryRepository.GetCategoryById(categoryId);}}
}
5. 实现编辑Category的方法
- 创建
EditCategoryUseCase.cs
,该类只负责传递一个categoryId和cateogry类,编辑Category
namespace UseCases.CategoriesUseCases
{public class EditCategoryUseCase{private readonly ICategoryRepository _categoryRepository;public EditCategoryUseCase(ICategoryRepository categoryRepository){this._categoryRepository = categoryRepository;}public void Excute(int categoryId,Category catogory){_categoryRepository.UpdateCategory(categoryId, catogory);}}
}
6. 实现获取删除Category的方法
- 创建
EditCategoryUseCase.cs
,该类只负责通过id删除category
namespace UseCases.CategoriesUseCases
{public class DeleteCategoryUseCase{private readonly ICategoryRepository _categoryRepository;public DeleteCategoryUseCase(ICategoryRepository categoryRepository){this._categoryRepository = categoryRepository;}public void Excute(int categoryId){_categoryRepository.DeleteCategoryById(categoryId);}}
}
5.2.3 创建ProductsUseCases
所有的UseCases只有一个公共的方法Excute()的好处:
- 单一职责,只要是usecase就只有Excute的方法
- 统一入口点都是Excute(),这样以后使用泛型或者反射都易于调用
- 从功能出发,如果我们需要一个处理products相关的业务,需要对products数据表有哪些操作
- 查询出所有的products, ViewProductsUseCase.cs
- 查询单个product的信息,ViewSelectedProductUseCase.cs
- 添加单个product,AddProductUseCase.cs
- 编辑单个product,EditProductUseCase.cs
- 删除单个product,DeleteProductUseCase.cs
- 可以看出来以上都是基础的增删改查,和CategoriesUseCases 基本一样,下面是products自己独有的方法
1. 创建一个AddProductUseCase
- 这里,我们先不用考虑程序里有什么接口,有什么功能,我们只需要写
- 创建一个Excute函数,在所有的UseCase的公共出口
- 函数里面里根据功能,这里是添加一个Products,所以直接调用
_productRepository.AddProduct(product);
- 通过构造函数从容器中拿我需要repository
2. 使用快捷键生成IProductRepository接口
- 使用快捷键 生成接口,将会自动在原目录下生成一个
IProductRepository.cs
的文件
IProductRepository.cs
namespace UseCases.ProductsUseCases
{public interface IProductRepository{}
}
- 将自动该文件移动到
DataStorePluginInterfaces
文件夹下
3. 通过快捷键生成接口对应的AddProduct方法
- 继续使用快捷键,往接口里添加AddProduct方法
- 此时,在
IProductRepository
接口里,我们的方法已经添加成功
using CoreBusiness;namespace UseCases.ProductsUseCases
{public interface IProductRepository{void AddProduct(Product product);}
}
4. 通过同样的方式,将剩下的几个UseCase完成
5. 通过快捷键将UseCase 提取成为接口
- 使用快捷件, 将所有的UseCases提成接口
- 会在同级目录下生成一个
IAddProductUseCase.cs
文件
using CoreBusiness;namespace UseCases.ProductsUseCases
{public interface IAddProductUseCase{void Execute(Product product);}
}
- 并且自动,添加了该接口
5.3 创建Plugins
Plugins就是真正实现ICategoryRepository的地方
5.3.1 实现一个内存存储的plugin
- 实现内存存储
1.在项目的根目录下创建一个Plugins文件夹,除了在vs里创建,还需要到项目的Folder里创建,因为vs创建的文件夹只是一个视图文件夹,真正的文件夹要在folder里创建
2. 创建一个Plugins.DateStore.InMemory类库,并在类库里创建CategoriesInMemoryRepository.cs
,该类库实现了ICategoryRepository
的所有功能
public class CategoriesInMemoryRepository : ICategoryRepository
- 将之前我们使用的内存存储和查询的方法,放到该类库内
- 由于方法的名称一样,这里直接使用即可
5.4 使用IOC在Controllers里
5.4.1 将CategoriesUseCases里的实现抽离成为接口
5.4.2 在CategoriesContollers里使用
- 注入
IViewCategoriesUseCase
- 在程序program入口,注入到容器中
- 注入
ICategoryRepository
数据库的接口