组合和存储库模式
Compositon and Repository pattern
我想通过注入在 CategoryRepository 内部使用 BloggingRepository class,并通过 CategoryRepository
访问控制器中的 BloggingRepository 方法
但是我无法实现这个,因为我无法访问 CategoryController 中的 bloggingRepo 字段,
所以我决定通过继承来实现。
由于我对oop没有经验,如果你能指导我为什么这种方法不起作用以及什么是合适的方法,我将不胜感激
在图片中,第一个设计有效,但第二个无效
class diagram image
我想在CategoryController的SaveCategory中使用BloggingRepository的Add方法
public interface IBloggingRepository
{
void Add<T>(T entity) where T : class;
void Delete<T>(T entity) where T : class;
Task<bool> SaveAll();
}
public interface ICategoryRepository : IBloggingRepository
{
Task<Category> GetCategory(int id);
}
public class BloggingRepository : IBloggingRepository
{
private readonly DataContext _context;
public BloggingRepository(DataContext context )
{
_context = context;
}
public void Add<T>(T entity) where T : class
{
_context.Add(entity);
}
}
public class CategoryRepository : ICategoryRepository
{
private readonly DataContext _context;
public readonly IBloggingRepository bloggingRepo;
public CategoryRepository(DataContext context, IBloggingRepository bloggingRepository)
{
_context = context;
bloggingRepo = bloggingRepository;
}
}
public class CategoryController : Controller
{
private readonly ICategoryRepository _categoryRepo;
public CategoryController(ICategoryRepository categoryRepo)
{
_categoryRepo = categoryRepo;
}
public async Task<IActionResult> SaveCategory()
{
// _categoryRepo.bloggingRepo.Add();
}
}
//Startup.cs
services.AddScoped<IBloggingRepository, BloggingRepository>();
services.AddScoped<ICategoryRepository, CategoryRepository>();
您的界面应描述您希望公开的所有方法。您的接口描述了给定的 class 将实现什么,而不是 如何实现 ,因此不会暴露 class 的状态。这很好,因为它允许您从该接口继承多个 class 并以不同的方式实现相同的方法。
在您的情况下,您希望能够从您的 CategoryRepository "Add"。幸运的是,您已经有了一个接口,IBloggingRepository。
如果您想要在 ICategoryRepository 的 IBloggingRepository 中找到相同的方法,也只需实现该接口即可!就是这么简单。
方法 1(不起作用):
在此方法中,CategoryRepository 将实现这两个接口,因此 CategoryRepository 必须公开 Add 方法。这也提供了从 class 外部隐藏 IBloggingRepository 的能力,以便隐藏状态。但是,这不起作用。为什么?只有 CategoryRepository class 实现了 ICategoryRepository 和 IBloggingRepository。 ICategoryRepository 未实现 IBloggingRepository,因此 Add 方法未在 ICategoryRepository 接口中公开,而这正是您的控制器中使用的方法。
// Implementation of the repository
// Does not expose Add to the ICategoryRepository !!!
public class CategoryRepository : ICategoryRepository, IBloggingRepository
{
private readonly DataContext _context;
private readonly IBloggingRepository _bloggingRepo;
public CategoryRepository(DataContext context, IBloggingRepository bloggingRepository)
{
_context = context;
_bloggingRepo = bloggingRepository;
}
// The implementation of the Add method
public void Add<T>(T entity) where T : class
{
_bloggingRepo.Add(entity);
}
}
方法二(正确答案):
通过这种方式,我们强制每个 ICategoryRepository 都必须实现 IBloggingRepository。这与方法 1 不同,因为第一种方法并不意味着每个 ICategoryRepository 都将实现 IBloggingRepostiory。
// Exposes the IBloggingRepository methods to ICategoryRepository
public interface ICategoryRepository : IBloggingRepository
{
}
// Implementation of the repository
public class CategoryRepository : ICategoryRepository
{
private readonly DataContext _context;
private readonly IBloggingRepository _bloggingRepo;
public CategoryRepository(DataContext context, IBloggingRepository bloggingRepository)
{
_context = context;
_bloggingRepo = bloggingRepository;
}
// The implementation of the Add method
public void Add<T>(T entity) where T : class
{
_bloggingRepo.Add(entity);
}
}
演示:
// Some model to be added to the repository
// Just for demonstration purposes
public class Blog
{
public Blog() { }
}
public class CategoryController : Controller
{
private readonly ICategoryRepository _categoryRepo;
public CategoryController(ICategoryRepository categoryRepo)
{
_categoryRepo = categoryRepo;
}
public async Task<IActionResult> SaveCategory()
{
// _categoryRepo.bloggingRepo.Add();
return await Task.Run(() =>
{
Blog blog = new Blog();
_categoryRepo.Add(blog);
// return IActionResult;
}).ConfigureAwait(false);
}
}
关于我为什么使用 ConfigureAwait(false) 的注释:
As a general rule, every piece of code that is not in a view model
and/or that does not need to go back on the main thread should use
ConfigureAwait false.
我想通过注入在 CategoryRepository 内部使用 BloggingRepository class,并通过 CategoryRepository
访问控制器中的 BloggingRepository 方法但是我无法实现这个,因为我无法访问 CategoryController 中的 bloggingRepo 字段, 所以我决定通过继承来实现。
由于我对oop没有经验,如果你能指导我为什么这种方法不起作用以及什么是合适的方法,我将不胜感激
在图片中,第一个设计有效,但第二个无效 class diagram image
我想在CategoryController的SaveCategory中使用BloggingRepository的Add方法
public interface IBloggingRepository
{
void Add<T>(T entity) where T : class;
void Delete<T>(T entity) where T : class;
Task<bool> SaveAll();
}
public interface ICategoryRepository : IBloggingRepository
{
Task<Category> GetCategory(int id);
}
public class BloggingRepository : IBloggingRepository
{
private readonly DataContext _context;
public BloggingRepository(DataContext context )
{
_context = context;
}
public void Add<T>(T entity) where T : class
{
_context.Add(entity);
}
}
public class CategoryRepository : ICategoryRepository
{
private readonly DataContext _context;
public readonly IBloggingRepository bloggingRepo;
public CategoryRepository(DataContext context, IBloggingRepository bloggingRepository)
{
_context = context;
bloggingRepo = bloggingRepository;
}
}
public class CategoryController : Controller
{
private readonly ICategoryRepository _categoryRepo;
public CategoryController(ICategoryRepository categoryRepo)
{
_categoryRepo = categoryRepo;
}
public async Task<IActionResult> SaveCategory()
{
// _categoryRepo.bloggingRepo.Add();
}
}
//Startup.cs
services.AddScoped<IBloggingRepository, BloggingRepository>();
services.AddScoped<ICategoryRepository, CategoryRepository>();
您的界面应描述您希望公开的所有方法。您的接口描述了给定的 class 将实现什么,而不是 如何实现 ,因此不会暴露 class 的状态。这很好,因为它允许您从该接口继承多个 class 并以不同的方式实现相同的方法。
在您的情况下,您希望能够从您的 CategoryRepository "Add"。幸运的是,您已经有了一个接口,IBloggingRepository。
如果您想要在 ICategoryRepository 的 IBloggingRepository 中找到相同的方法,也只需实现该接口即可!就是这么简单。
方法 1(不起作用): 在此方法中,CategoryRepository 将实现这两个接口,因此 CategoryRepository 必须公开 Add 方法。这也提供了从 class 外部隐藏 IBloggingRepository 的能力,以便隐藏状态。但是,这不起作用。为什么?只有 CategoryRepository class 实现了 ICategoryRepository 和 IBloggingRepository。 ICategoryRepository 未实现 IBloggingRepository,因此 Add 方法未在 ICategoryRepository 接口中公开,而这正是您的控制器中使用的方法。
// Implementation of the repository
// Does not expose Add to the ICategoryRepository !!!
public class CategoryRepository : ICategoryRepository, IBloggingRepository
{
private readonly DataContext _context;
private readonly IBloggingRepository _bloggingRepo;
public CategoryRepository(DataContext context, IBloggingRepository bloggingRepository)
{
_context = context;
_bloggingRepo = bloggingRepository;
}
// The implementation of the Add method
public void Add<T>(T entity) where T : class
{
_bloggingRepo.Add(entity);
}
}
方法二(正确答案): 通过这种方式,我们强制每个 ICategoryRepository 都必须实现 IBloggingRepository。这与方法 1 不同,因为第一种方法并不意味着每个 ICategoryRepository 都将实现 IBloggingRepostiory。
// Exposes the IBloggingRepository methods to ICategoryRepository
public interface ICategoryRepository : IBloggingRepository
{
}
// Implementation of the repository
public class CategoryRepository : ICategoryRepository
{
private readonly DataContext _context;
private readonly IBloggingRepository _bloggingRepo;
public CategoryRepository(DataContext context, IBloggingRepository bloggingRepository)
{
_context = context;
_bloggingRepo = bloggingRepository;
}
// The implementation of the Add method
public void Add<T>(T entity) where T : class
{
_bloggingRepo.Add(entity);
}
}
演示:
// Some model to be added to the repository
// Just for demonstration purposes
public class Blog
{
public Blog() { }
}
public class CategoryController : Controller
{
private readonly ICategoryRepository _categoryRepo;
public CategoryController(ICategoryRepository categoryRepo)
{
_categoryRepo = categoryRepo;
}
public async Task<IActionResult> SaveCategory()
{
// _categoryRepo.bloggingRepo.Add();
return await Task.Run(() =>
{
Blog blog = new Blog();
_categoryRepo.Add(blog);
// return IActionResult;
}).ConfigureAwait(false);
}
}
关于我为什么使用 ConfigureAwait(false) 的注释:
As a general rule, every piece of code that is not in a view model and/or that does not need to go back on the main thread should use ConfigureAwait false.