我认为很容易理解,在查看您提供的示例时,您很容易将IProductDal 接口称为多余的。事实上,它并没有向类型ProductDal 添加任何额外的成员,因为接口IProductDal 和泛型类EfEntityRepositoryBase 是使用相同的泛型参数类型Product 定义的。由于这些教学示例不是在实际应用程序代码的上下文中设置的,因此它们背后的真实意图或想法并不容易理解。
作为旁注,您应该知道,如果类 EfEntityRepositoryBase<TEntity> 将使用与 Product 不同的泛型参数类型定义,例如,int、ProductDal 将有两个实现/成员重载IEntityRepository<T> 接口。
例如:
public class ProductDal : EfEntityRepositoryBase<int>, IProductDal
{
// Implementation of IProductDal. The EfEntityRepositoryBase type provides another 'int' overload
public void Add(Product entity) {}
}
void Main()
{
var productDal = new ProductDal();
// Implementation of IEntityRepository<int> provided by class EfEntityRepositoryBase<int>
productDal.Add(6);
// Implementation of 'IProductDal' (provided by class 'ProductDal')
productDal.Add(new Product());
}
您可以看到您提供的示例显示了一个特殊情况,其中 EfEntityRepositoryBase<TEntity> 已经提供了 IEntityRepository<Product> 和 IProductDal 接口的实现。
回到你的例子:如果你使用类型转换,你会发现另一个使用所谓的冗余类型定义的用例:
Given 是您的 ProductDal 类型,具有以下类签名
public class ProductDal : EfEntityRepositoryBase<int>, IProductDal
您现在有多种类型可用于访问IEntityRepository<Product> 的实现
void Main()
{
// Create an instance of ProducDal
ProductDal productDal = new ProductDal();
/* Use the instance of ProductDal with multiple overloads
to show implicit type casting */
UseProductDal(productDal);
UseIProductDal(productDal);
UseIEntityRepository(productDal);
UseEntityRepository(productDal);
}
void UseProductDal(ProductDal productDal)
{
// Instantiate the argument
var product = new Product();
productDal.Add(product);
}
void UseIProductDal(IProductDal productDal)
{
// Instantiate the argument
var product = new Product();
productDal.Add(product);
}
void UseIEntityRepository(IEntityRepository<Product> productDal)
{
// Instantiate the argument
var product = new Product();
productDal.Add(product);
}
void UseEntityRepositoryBase(EntityRepositoryBase<Product> productDal)
{
// Instantiate the argument
var product = new Product();
productDal.Add(product);
}
这显示了如何使用隐式类型转换以及如何使用接口。
您现在看到虽然EntityRepositoryBase<Product> 已经实现了IEntityRepository<Product>,但仍然让ProductDal 额外实现IProductDal 接口是非常有意义的,以便在只有IProductDal 接口已知的情况下启用ProductDal。
您可以使用接口转换来隐藏成员。例如,如果您向每个接口添加独占成员,则只有在将实现者强制转换为相应接口时才能访问此成员:
public interface IEntityRepository<T>
{
void Add(T entity);
}
public interface IProductDal: IEntityRepository<Product>
{
// Exclusive member. Will be only visible when accessed through this interface.
int GetProductCount();
}
Given 是您的 ProductDal 类型,具有以下类签名
public class ProductDal : IEfEntityRepository<int>, IProductDal
void Main()
{
// Create an instance of ProducDal
ProductDal productDal = new ProductDal();
/* Use the instance of ProductDal with multiple overloads
to show implicit type casting */
UseProductDal(productDal);
UseIProductDal(productDal);
UseIEntityRepository(productDal);
UseEntityRepository(productDal);
}
// All implemented interfaces are visible since there is no casting involved.
// All members are referenced via the implementor type ProductDal.
void UseProductDal(ProductDal productDal)
{
// Instantiate the argument
var product = new Product();
productDal.Add(product);
int productCount = productDal.getProductCount();
}
// Only 'IProductDal' is visible since there is an implicit cast to an interface type involved
void UseIProductDal(IProductDal productDal)
{
// Instantiate the argument
var product = new Product();
// 'Add()' is provided by 'IEntityRepository<T>',
// which is implemented by 'IProductDal' and therefore "visible"
productDal.Add(product);
// 'GetProductCount()' is provided by 'IProductDal'
int productCount = productDal.GetProductCount();
}
// Only 'IEntityRepository<T>' is visible since there is an implicit cast to the interface type
void UseIEntityRepository(IEntityRepository<Product> productDal)
{
// Instantiate the argument
var product = new Product();
productDal.Add(product);
// 'GetProductCount()' is only available via the 'IProductDal' interface.
// It's not visible here.
//int productCount = productDal.GetProductCount();
}