在我的数据访问层(它自己的库(中,我有一个 POCO 类,它表示我的域对象的数据库表。 我们可以举一个作为例子,我们称之为MyClassDTO
,即使有几十个类似的对象。
在我的业务逻辑层中,它也在它自己的库中(并引用 DAL 库(,它为每个对象提供了实际的域对象类。 让我们使用MyClass
.
BLL公开了一堆类,如MyClassBll
,可以在演示项目中实例化,以便访问域逻辑和数据。
为了让我的生活更轻松,大多数 BLL 对象(如 MyClassBll
(都继承自一个通用抽象Bll<TModel,TDto>
类。 因此,例如MyClassBll
声明如下:
Public Class MyClassBll : Bll<MyClass,MyClassDto>
这里的想法是,BLL 的工作是获取域对象(表示层将使用的语言(将它们转换为 DTO(DAL 将要使用的语言(,反之亦然。
它确实使创建各种对象变得轻而易举,特别是因为我可以在需要时覆盖通用实现,并且在它简单时不理会它。 目前为止,一切都好。
当我开始在演示文稿中使用它时,我才遇到问题。 我包括 BLL 库作为参考,但它不允许我使用任何MyClassBLL,
方法,因为它不知道 MyClassDto
的定义,这是在MyClassBll
的元数据中,因为它的定义。
我不希望我的表示层必须知道我的 DAL 类。 如何满足编译器的要求? 有没有办法在表示层中进一步隐藏我的 DAL,同时仍然保持当前设计的灵活性?
作为参考,我的通用 BLL 类如下所示:
public abstract class Bll<TModel, TDto> : IBll<TModel, TDto>
where TModel : class
where TDto : class
{
protected User User;
protected static string[] AdminGroups;
protected bool IsAdmin;
protected static Func<UnitOfWork, GenericRepository<TDto>> Repository;
private void AdminCheck()
{
if (!IsAdmin)
{
throw new SecurityException("That Action Requires Admin Privileges");
}
}
public Bll(User user)
{
StaticMapBulder.initialize();
if (User == null)
{
throw new ArgumentNullException("User Can not be null");
}
user = User;
IsAdmin = false;
foreach (var AdminGroup in AdminGroups)
{
if (user.IsInGroup(AdminGroup))
{
IsAdmin = true;
}
}
}
public virtual TModel Insert(TModel ItemToAdd)
{
AdminCheck();
using (var uow = new UnitOfWork())
{
var OutgoingDto = MapModelToDto(ItemToAdd);
var InboundDto = Repository(uow).Insert(OutgoingDto);
uow.Save();
return MapDtoToModel(InboundDto);
}
}
public virtual List<TModel> GetAll()
{
using (var uow = new UnitOfWork())
{
var InboundDto = Repository(uow).Get();
var ModelList = new List<TModel>();
foreach (var item in InboundDto)
{
ModelList.Add(MapDtoToModel(item));
}
return ModelList;
}
}
public virtual TModel GetByID(int ID)
{
using (var uow = new UnitOfWork())
{
var InboundDto = Repository(uow).GetByID(ID);
return MapDtoToModel(InboundDto);
}
}
public virtual void Update(TModel ItemToUpdate)
{
AdminCheck();
using (var uow = new UnitOfWork())
{
var OutboundDto = MapModelToDto(ItemToUpdate);
Repository(uow).Update(OutboundDto);
uow.Save();
}
}
public virtual void Delete(TModel ItemToDelete)
{
using (var uow = new UnitOfWork())
{
var OutboundDto = MapModelToDto(ItemToDelete);
Repository(uow).Delete(OutboundDto);
uow.Save();
}
}
public virtual void DeleteByID(int ID)
{
using (var uow = new UnitOfWork())
{
Repository(uow).Delete(ID);
uow.Save();
}
}
virtual public TModel MapDtoToModel(TDto Dto)
{
return Mapper.Map<TModel>(Dto);
}
virtual public TDto MapModelToDto(TModel Model)
{
return Mapper.Map<TDto>(Model);
}
}
}
这使得该类的通用实现如下所示:
public class MyClassBll : Bll<MyClass, MyClassDto>
{
public MyClassBll(User user)
: base(user)
{
}
new protected static Func<UnitOfWork, GenericRepository<MyClassDto>> Repository = x => x.MyClassRepository;
new protected static string[] AdminGroups = { "MyClassAdministrators" };
}
我不希望我的表示层必须知道我的 DAL 类。如何满足编译器的要求?有没有办法我可以 进一步从表示层隐藏我的 DAL,同时仍保留 我当前设计的灵活性?
这不是你需要满足的编译器,而是你的设计要求。
您为什么不想让演示文稿了解 DTO?DTO 的职责是在组件之间传递。使用 DTO 将数据从业务类传递到演示文稿是完全可以接受的。
您是正确的,因为您希望在演示文稿中隐藏您的 DAL。您需要更改设计才能启用此功能。
我推荐一个依赖于您的 DAL 的存储库。此存储库是唯一依赖于 DAL 的组件。现在,您的业务类可以在存储库上调用 CRUD 操作。您的业务类对存储库返回的数据执行一些转换和计算。如果您需要更新演示文稿,您可以向其发送现在转换的数据的模型或 DTO。关注点是分开的。