C# 太多的抽象/接口

C# 太多的抽象/接口,c#,design-patterns,data-access-layer,C#,Design Patterns,Data Access Layer,我正在设计我的数据访问代码,数据将被存储在RavenDB中,我试图看看我当前的设计是否对我将要拥有的接口数量有太多的抽象 我将有一个DTO,它将只保存数据,然后我将有一个实体(或模型、业务或任何你称之为它们的东西)对象,它将有额外的功能。我还将为每个实体提供一个接口,定义它需要的数据。例如: interface IUser { string Id { get; } string Username { get; } string Password { get; }

我正在设计我的数据访问代码,数据将被存储在RavenDB中,我试图看看我当前的设计是否对我将要拥有的接口数量有太多的抽象

我将有一个DTO,它将只保存数据,然后我将有一个实体(或模型、业务或任何你称之为它们的东西)对象,它将有额外的功能。我还将为每个实体提供一个接口,定义它需要的数据。例如:

interface IUser
{
    string Id { get; }
    string Username { get; }
    string Password { get; }
    bool ResetPassword { get; }
}

class UserDTO : IUser
{
    public string Id { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }

    public UserDTO()
    {
        Id = null;
        Username = null;
        Password = null;
        ResetPassword = false;
    }
}

class User : IUser
{
    public string Id { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }

    public User()
    {
        Id = null;
        Username = null;
        Password = null;
        ResetPassword = false;
    }

    public User(IUser user)
    {
        Id = user.Id;
        Username = user.Username;
        Password = user.Password;
        ResetPassword = user.ResetPassword;
    }

    public ResetPassword()
    {
        Id = null;
        Username = null;
        Password = null;
    }
}
interface IDataRepository<T>
{
    bool Save(T entity);
    bool Delete(T entity);
}

interface IUserRepository : IDataRepository<IUser>
{
    IUser Load(string key);
    IUser LoadByLogin(string username, string password);
}

class UserRepository : IUserRepository
{
    bool Save(T entity)
    {
        //save code
    }

    bool Delete(T entity)
    {
        //delete code
    }

    IUser Load(string key)
    {
        //load code
    }

    IUser LoadByLogin(string username, string password)
    {
        //load code
    }
}
我希望每个实体都有一个接口的原因是,我希望确保
EntityDTO
实体
都具有所需的共享数据

现在,为了检索和保存数据,我将使用repository模式。我将拥有一个名为
IDataRepository
的通用接口,然后每个实体将拥有自己的存储库接口。例如:

interface IUser
{
    string Id { get; }
    string Username { get; }
    string Password { get; }
    bool ResetPassword { get; }
}

class UserDTO : IUser
{
    public string Id { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }

    public UserDTO()
    {
        Id = null;
        Username = null;
        Password = null;
        ResetPassword = false;
    }
}

class User : IUser
{
    public string Id { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }

    public User()
    {
        Id = null;
        Username = null;
        Password = null;
        ResetPassword = false;
    }

    public User(IUser user)
    {
        Id = user.Id;
        Username = user.Username;
        Password = user.Password;
        ResetPassword = user.ResetPassword;
    }

    public ResetPassword()
    {
        Id = null;
        Username = null;
        Password = null;
    }
}
interface IDataRepository<T>
{
    bool Save(T entity);
    bool Delete(T entity);
}

interface IUserRepository : IDataRepository<IUser>
{
    IUser Load(string key);
    IUser LoadByLogin(string username, string password);
}

class UserRepository : IUserRepository
{
    bool Save(T entity)
    {
        //save code
    }

    bool Delete(T entity)
    {
        //delete code
    }

    IUser Load(string key)
    {
        //load code
    }

    IUser LoadByLogin(string username, string password)
    {
        //load code
    }
}
接口IDataRepository
{
bool-Save(T实体);
bool删除(T实体);
}
接口IUserRepository:IDataRepository
{
IUser加载(字符串键);
IUser LoadByLogin(字符串用户名、字符串密码);
}
类UserRepository:IUserRepository
{
布尔保存(T实体)
{
//保存代码
}
布尔删除(T实体)
{
//删除代码
}
IUser加载(字符串键)
{
//加载代码
}
IUser LoadByLogin(字符串用户名、字符串密码)
{
//加载代码
}
}
我希望每个实体都有一个存储库接口的原因是,如果我需要为不同的实体使用不同的数据存储选项,我可以这样做


这看起来是不是太抽象了?

我认为这种模式有好有坏。如果您的DTO要与实体匹配,为什么要使用DTO?在某些系统中,这是需要发生的事情,而在另一些系统中,这是浪费时间。根据ORM,实体通常有行李,不能很好地序列化。如果使用该接口,DTO和实体之间的映射可以通过AutoMapper完成,并且每次都可以正常工作。您是否需要让实体类与DTO位于单独的DLL中?如果是这样的话,我认为你的模型是可行的。

你所拥有的,在本质上,对我来说似乎很好


但是,除非您进一步区分DTO和Entity类,并且明确需要将两者分开,否则我只需要将
User
扩展
UserDTO
并一起删除接口。这样,您就可以删除当前的代码冗余。

是的,这太抽象了。具体来说,我认为不需要
UserDTO
对象类


IUser
本身应该定义数据存储库完成其工作所需的完整接口。如果存储库中有一个实现了
IUser
的对象,比如
User
,那么它应该能够很好地存储数据。而且,由于接口是在最低级别定义的,省略
UserDTO
对象不会产生任何依赖性问题。

为什么要区分
User
UserDTO
?这看起来像抽象吗?什么意思?你能说明你想要实现什么吗?所以你从一个存储库中加载IUser。你下一步要做什么?将其转换为用户?此外,从提供的信息来看,没有证据表明DTO是真正必要的。很抱歉,我的最后一个问题中遗漏了这个词,更新。我认为我们对系统了解不够,不能说它太多。如果这是一个为项目在公司内部分发的DLL呢,您是否仍希望传回可能有钩子的实体,而您不想让其访问?@CrazyDart-如果OP担心实现存储库层的人员将在其IUser实例上使用反射来访问受限功能,那么这就是问题中真正应该阐明的东西!