在使用抽象泛型类时最小化依赖项要求

本文关键字:依赖 最小化 抽象 泛型类 | 更新日期: 2023-09-27 18:34:53

在我的数据访问层(它自己的库(中,我有一个 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。关注点是分开的。