c# - 需要一些帮助来解决我的 DAL 中的主要抽象模式问题

标签 c# .net generics design-patterns abstract-class

我的数据访问层给自己带来了一点问题。在此特定实例中,我有一个表,其中可能包含 5 种类型的“实体”。这些基本上是公司、客户、站点等。类型由表中的 PositionTypeId 决定。它们都在同一个表中,因为它们都具有相同的数据结构; PositionId、描述和代码

我有一个主要的抽象类如下:

public abstract class PositionProvider<T> : DalProvider<T>, IDalProvider where T : IPositionEntity
{
    public static PositionProvider<T> Instance
    {
        get
        {
            if (_instance == null)
            {
                // Create an instance based on the current database type
            }
            return _instance;
        }
    }
    private static PositionProvider<T> _instance;

    public PositionType PositionType
    {
        get
        {
            return _positionType;
        }
    }
    private PositionType _positionType;

    // Gets a list of entities based on the PositionType enum's value.
    public abstract List<T> GetList();

    internal void SetPositionType(RP_PositionType positionType)
    {
        _positionType = positionType;
    }

}

然后我希望能够将所有通用代码放入一个基于 SQL 或 Oracle 的继承类中。这是我的 SQL 实现:

public class SqlPositionProvider<T> : PositionProvider<T> where T : IPositionEntity
{
        public override List<T> GetList()
        {
            int positionTypeId = (int)this.PositionType;
            using (SqlConnection cn = new SqlConnection(Globals.Instance.ConnectionString))
            {
                SqlCommand cmd = new SqlCommand("Get_PositionListByPositionTypeId", cn);
                cmd.Parameters.Add("@PositionTypeId", SqlDbType.Int).Value = positionTypeId;
                cmd.CommandType = CommandType.StoredProcedure;
                cn.Open();
                return this.GetCollectionFromReader(this.ExecuteReader(cmd));
            }
        }
}

然后我为每种类型创建了一个类,如下所示(以 CustomerProvider 为例):

public class CustomerProvider
{
    public static PositionProvider<CustomerEntity> Instance
    {
        get
        {
            if ((int)PositionProvider<CustomerEntity>.Instance.PositionType == 0)
            {
                PositionProvider<CustomerEntity>.Instance.SetPositionType(PositionType.Customer);
            }
            return PositionProvider<CustomerEntity>.Instance;
        }
    }
}

这一切都非常有效......直到我意识到我有一些特定于某些职位类型的功能。 IE。我需要能够根据用户权限获取所有客户(这是一个 IPositionType)。

所以我需要添加另一个抽象方法:

public abstract List<CustomerEntity> GetCustomersByUserPermission(Guid userId);

现在,显然我不希望在我的 PositionProvider 抽象类中使用此方法,因为这意味着在处理网站/公司提供商时会出现该方法。

我怎样才能添加这个和其他额外的方法,而不必在 SqlPositionProvider 中复制代码?

编辑:

我想到的唯一想法是将 PositionProvider 分离为 CustomerProvider、SiteProvider 等的公共(public)属性:

public abstract class CustomerProvider
{

    public CustomerProvider()
    {
        this.Common.SetPositionType(PositionType.Customer);
    }

    public PositionProvider<CustomerEntity> Common
    {
        get
        {
            if (_common == null)
            {
                DalHelper.CreateInstance<PositionProvider<CustomerEntity>>(out _common);
            }
            return _common;
        }
    }
    private PositionProvider<CustomerEntity> _common;

    public static CustomerProvider Instance
    {
        get
        {
            if (_instance == null)
            {
                DalHelper.CreateInstance<CustomerProvider>(out _instance);
            }
            return _instance;
        }
    }
    private static CustomerProvider _instance;

    public abstract List<CustomerEntity> GetCustomersByUserPermission(Guid userId);

}

这将允许我将特定代码放在 CustomerProvider.Instance.MyNonGenericMethod() 中,然后访问 PositionProvider 我可以做 CustomerProvider.Instance .Common.GetList()... 不过这看起来确实有点像 hack。

最佳答案

如果我理解正确,你需要一种方法来在子类中包含一些方法,但不是在所有子类中。

如果您可以对所需的额外方法进行分组,则可以使用一个接口(interface),实现它,并在您的子级(组合)中使用这个新类的实例。

对此的简化是所有子类的存储库模式(此示例不使用接口(interface))。

[注意:代码无法编译,仅供演示使用]

public class PositionProviderRepository
{
    public List<T> GetList()
        {
            int positionTypeId = (int)this.PositionType;
            using (SqlConnection cn = new SqlConnection(Globals.Instance.ConnectionString))
            {
                SqlCommand cmd = new SqlCommand("Get_PositionListByPositionTypeId", cn);
                cmd.Parameters.Add("@PositionTypeId", SqlDbType.Int).Value = positionTypeId;
                cmd.CommandType = CommandType.StoredProcedure;
                cn.Open();
                return this.GetCollectionFromReader(this.ExecuteReader(cmd));
            }
        }
    public List<CustomerEntity> GetCustomersByUserPermission(Guid userId) {
      //TODO: implementation
    }
}

然后在所有实体(如 CustomerEntity)中使用此类。

这可以有效地替代您的类 SqlPositionProvider<T>但我不确定我是否正确理解了您的架构,您的层次结构非常复杂。

关于c# - 需要一些帮助来解决我的 DAL 中的主要抽象模式问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1661549/

相关文章:

c# - 使用 QBFC 时的 HRESULT 80040154

.Net:如何将类属性转换为输出 xml 元素?

java - 底层平台是否会影响任何网站或网络应用程序的速度?

c# - 将简单的 C# DLL 转换为 COM 互操作组件

java - 了解 Java 泛型子类型

c# - 将 List<string> 分成大小相等的子列表 N

c# - ASP.Net MVC TryUpdateModel() 等效于在 Windows 应用程序中使用

c# 根据对象的属性对对象列表进行排序

c# - 为什么不能为泛型类型推断类型参数?

java - 公共(public)类 Extra<BASE> 扩展 BASE