覆盖通用基本类型的方法

时间:2019-11-19 08:19:28

标签: c# .net generics inheritance interface

我当前的结构如下:

public class CustomerRepository
{
    // ..

    public virtual Customer LoadCustomer()
    {
        // ...
    }
}

public class OracleCustomerRepository : CustomerRepository
{
    private OracleConnection oracleConnection;

    public OracleCustomerRepository()
    : base(){
        if(this.EnsureIsConnected()){
             // ...
        }
    }

    private bool EnsureIsConnected(){
        // ..
    }

    public override Customer LoadCustomer(){
        // ..
    }
}

效果很好,除了以下事实:-对于每个OracleRepository-我必须再次编写方法EnsureIsConnected,我必须再次声明已归档的OracleConnection等。

我想抽象一下。我的第一个想法是使用Interface,但这不能解决重复代码的问题。我的第二个想法是将基类CustomerRepository用作另一个新基类OracleRepository<T>的通用类型,该基类随后定义了公共例程。

问题是:据我所知,无法override这种通用类型的virtual方法,例如CustomerRepository

我就是这么认为的。

public class OracleRepository<T> where T : class{

    public OracleRepository(){
        this.EnsureIsConnected());
    }

    protected OracleConnection oracleConnection;

    protected EnsureIsConnected(){
        // ...
    }
}

public class OracleCustomerRepository : OracleRepository<CustomerRepository>{

    // ..

    // this is not possible, defined in CustomerRepository
    public override Customer LostCustomer(){

    }
}

注意:CustomerRepository不是我唯一的存储库。这主要是我试图找到更好的解决方案的原因。

关于如何处理此问题的任何建议?

2 个答案:

答案 0 :(得分:2)

我的第一个想法是您的抽象似乎有点泄漏。 我通常要做的是使用以下方法创建与数据库引擎交互的界面:

public interface IPersistence
{
    void ExecuteOperation(string prodecureName, Dictionary<string, object> parameters);
    T ExecuteSingle(string procedureName, Dictionary<string, object> parameters, Func<IDataReader, T> rowReader);
    List<T> ExecuteMultirow(string procedureName, Dictionary<string, object> parameters, 
Func<IDataReader, T> rowReader);
}

然后在存储库中将其作为依赖项,并从IoC容器中确定要使用的实现。 因此,在您的代码中您将拥有:

public class CustomerRepository
{
    private readonly IPersistence persistence;

    public CustomerRepository(IPersistence persistence)
    {
        this.persistence = persistence;
    }

    public virtual Customer LoadCustomer()
    {
        // preparation code
        return this.persistence.ExecuteSingle("some procedure", parameters, r => new Customer((int)r["Id"], (string)r["DisplayName"]));
    }
}

答案 1 :(得分:1)

可以这样做吗?还是这不是您想要的?

public abstract class CustomerRepository<T>
{
    protected OracleConnection oracleConnection;

    protected CustomerRepository() : base(){
        if(EnsureIsConnected()){
            // ...
        }
    }

    protected bool EnsureIsConnected()
    {
        return true;
    }

    public abstract T Load();
}

public class OracleCustomerRepository : CustomerRepository<Customer>
{
    public override Customer Load(){
        return new Customer();
    }
}