我当前的结构如下:
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(){
}
}
关于如何处理此问题的任何建议?
您可以这样做吗?还是这不是您想要的?
public abstract class CustomerRepository<T>
{
protected OracleConnection oracleConnection;
protected bool EnsureIsConnected()
{
return true;
}
public abstract T LoadCustomer();
}
public class OracleCustomerRepository : CustomerRepository<Customer>
{
public OracleCustomerRepository() : base(){
if(base.EnsureIsConnected()){
// ...
}
}
public override Customer LoadCustomer(){
return new Customer();
}
}
我首先想到的是您的抽象似乎有点泄漏。我通常要做的是使用类似方法创建与数据库引擎交互的界面:
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"]));
}
}