基于接口的方法解决歧义

本文关键字:方法 解决 歧义 接口 于接口 | 更新日期: 2023-09-27 18:04:16

我尝试了下面的存储库模式实现

interface IRepository<T>
{
    IQueryable<T> All { get; }
    T Find(object id);
    void Insert(T model); 
}

然后我有IAdminRepository定义在下面

interface IAdminRepository : IRpository<Role>, IRepository<User>
{
}
public class AdminRepository:IAdminRepository
{
    IQueryable<User> IRepository<User>.All
    {
        get { throw new NotImplementedException(); }
    }
    User IRepository<User>.Find(object id)
    {
        throw new NotImplementedException();
    }
    void IRepository<User>.Insert(User model)
    {
        throw new NotImplementedException();
    }
    IQueryable<Role> IRepository<Role>.All
    {
        get { throw new NotImplementedException(); }
    }
    Role IRepository<Role>.Find(object id)
    {
        throw new NotImplementedException();
    }
    void IRepository<Role>.Insert(Role model)
    {
        throw new NotImplementedException();
    }
}

在我的业务层,我使用基于接口的调用。

public interface IAdminService
{
    bool CreateUser(User user);        
    List<User> GetAllUsers();
}
public class AdminService : IAdminService
{
    private readonly IAdminRepository AdminRepository;
    public AdminService(IAdminRepository _adminRepository)
    {
        AdminRepository = _adminRepository;
    }
    public bool CreateUser(User user)
    {
        AdminRepository.Insert(user);
        return true;
    }
    public List<User> GetAllUsers()
    {
        return AdminRepository.All; // Here is error 
    }
}

错误:IRepository之间的歧义。所有,IRepository.All .

如何解决这个问题?我以这种方式使用存储库模式的方法有什么问题?

基于接口的方法解决歧义

我猜这行

return AdminRepository.All; // Here is error 

应为

return ((IRepository<User>)AdminRepository).All.ToList();

您可能注意到,如果不显式地编写要实现的接口,您将无法声明.All。这是因为,对于给定的类,具有相同名称的两个属性不能有不同的返回类型。

调用时也是如此。您必须准确地说明要调用的是哪个属性。这是通过将对象强制转换为所需的接口来实现的。

无论如何,看起来您最终将实现所有实体类型的存储库。对于可以从相同机制中检索的实体类型,您应该只实现一次IRepository<T>

如果您希望您的存储库只应用于某些类,您可以,例如,用接口标记这些类。以IEntity为例

public interface IEntity
{
}
然后

public interface IRepository<T> where T:IEntity
{
    IQueryable<T> All { get; }
    T Find(object id);
    void Insert(T model);
}

你甚至可以拥有只适用于你标记为db实体的数据库存储库,像这样:

public interface IDbEntity: IEntity
{
}

public class DbRepository<T> : IRepository<T> where T:IDbEntity
{
    public IQueryable<T> All { get; private set; }
    public T Find(object id)
    {
        throw new NotImplementedException();
    }
    public void Insert(T model)
    {
        throw new NotImplementedException();
    }
}

消除调用歧义的一种简单方法是创建混叠方法:

public class AdminRepository : IAdminRepository {
  public IQueryable<User> AllUsers {
    get { throw new NotImplementedException(); }
  }
  public IQueryable<Role> AllRoles {
    get { throw new NotImplementedException(); }
  }
  IQueryable<User> IRepository<User>.All {
    get { return AllUsers; }
  }
  IQueryable<Role> IRepository<Role>.All {
    get { return AllRoles; }
  }
  ...
}