摆脱一般声明

时间:2014-03-20 15:09:15

标签: c# generics repository-pattern

我正在尝试定义适当的接口和类来创建存储库接口和基础存储库类,它可以完成每个存储库所需的常见事务。然后我还想为特定的实体类型定义一个存储库,该存储库也在它自己的接口中定义。

到目前为止,我已经提出以下建议:

// The repository interface:

/// <summary>
/// Defines the methods of the base repository
/// </summary>
/// <typeparam name="TEntity">An entity class</typeparam>
public interface IRepository<TEntity> where TEntity : class
{
    /// <summary>
    /// Retrieves all the entities
    /// </summary>
    /// <returns>A query able set of entities</returns>
    IQueryable<TEntity> Get();
}

// An abstract implementation of it, which all repositories will inherit from:

/// <summary>
/// Represents the base repository from which all database bound repositories inherit
/// </summary>
/// <typeparam name="TEntity">The entity type this repository handles</typeparam>
public abstract class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
    /// <summary>
    /// Retrieves all the entities
    /// </summary>
    /// <returns>A query able set of entities</returns>
    public virtual IQueryable<TEntity> Get()
    {
        return this.Context.Set<TEntity>();
    }
}

用户实体的特定界面:

/// <summary>
/// Represents a user
/// </summary>
public class User
{
    public string Login { get; set; }
    public string Password { get; set; }
}

/// <summary>
/// Defines the interface for user repository implementations
/// </summary>
/// <typeparam name="TEntity">A user entity</typeparam>
public interface IUserRepository<TEntity> : IRepository<TEntity> where TEntity : User
{
    void Authenticate(TEntity user);
}

// and it's implementation:

/// <summary>
/// Represents a database bound repository that handles user entities
/// </summary>
/// <typeparam name="TEntity">A user entity</typeparam>
public class UserRepository<TEntity> : BaseRepository<TEntity>, IUserRepository<TEntity> where TEntity : User
{
    public void Authenticate(TEntity user)
    {
        // do some stuff here
    }
}

以上工作正常但是为了实例化UserRepository我必须写var users = new UserRepository<User>()

很明显,UserRepository中的泛型只能是User类型,所以我想找到一种不必显式写入的方法。我希望能够代之以var users = new UserRepository()

另外,在编写测试时,我必须像这样创建IUserRepository的模拟:

var usersMock = new Mock<IUserRepository<User>>();

我也希望能够写出这样的内容:

var usersMock = new Mock<IUserRepository>();

这可能是一个XY问题,因此我对不同的整体实施建议持开放态度。

2 个答案:

答案 0 :(得分:4)

您可以实现特定的接口:

public interface IUserRepository : IRepository<User>
{
    void Authenticate(Useruser);
}

// and it's implementation:

public class UserRepository : BaseRepository<User>, IUserRepository
{
    public void Authenticate(User user)
    {
        // do some stuff here
    }
}

您的接口可以具有泛型类型参数,但是当您实现接口时,您可以指定这些参数。您的实现也不需要是通用的

答案 1 :(得分:2)

如果您总是在某个班级使用特定的课程或界面,那么

继承/实现,那么你不需要对它进行泛型化。

以下是一个示例,希望您的要求是:

public interface IUserRepository : IRepository<IUser>
{
    void Authenticate(IUser user);
}

public class UserRepository : BaseRepository<User>, IUserRepository
{
    public void Authenticate(IUser user)
    {
        // do some stuff here
    }
}

您现在可以实例化并模拟,而无需指定可能始终相同的泛型。

var repository = new UserRepository();