接口和依赖注入在C#中正确使用

时间:2014-09-05 17:32:28

标签: c# interface dependency-injection loose-coupling

我有一个界面" IUser"和一个班级"用户"实施" IUser"。我还有一个存储库接口" IUserRepository"。

我介于这两个选项之间:

public interface IUserRepository
{
    List<User> getAll();
    void addUser(User user);
    void alterUser(User user);
    void deleteUser(string ID);
    bool validateLogin(string session_user, string session_pass);
    User getUserByID(int ID);
    User getUserByNombre(string name);
    User getUserBySessionUser(string session_user);
}

和这个

public interface IUserRepository
{
    List<IUser> getAll();
    void addUser(IUser user);
    void alterUser(IUser user);
    void deleteUser(string ID);
    bool validateLogin(string session_user, string session_pass);
    IUser getUserByID(int ID);
    IUser getUserByNombre(string name);
    IUser getUserBySessionUser(string session_user);
}

这是我的困惑。我的存储库接口中的方法是否应该返回实际的实现或接口?正如你在我的第一个选项中看到的那样,我正在回归&#34;用户&#34;实例。我应该回过头来松散地结合代码?

但是如果我在用户存储库的实际实现中选择第二个,我将只能访问我在IUser接口中声明的方法和属性。

例如,如果我从服务中调用addUser方法传递User类的实例:

   myRepositoryImplementation.addUser(UserInstance);

然后我真正的存储库将会像这样

  private readonly IUser user;
  public void addUser(IUser _user)
  {
    this.user=_user;
  }

好有效的捕捉!但是我只能访问最初在IUser接口中声明的方法和属性,而不能访问我的User实例中声明的任何新方法或属性。

如果我调用getUserByID方法,我将收到一个IUser实例。

所以要恢复这个

1)。这些有效的方法吗?
2)。如果这些是有效的方法,我应该用它来保存或保持代码解耦? 3)。如果我选择第二个,如果它是有效的,那么我应该在界面中声明我将要使用的所有内容吗?我的意思是属性和方法? 3)。有更好的主意吗?

3 个答案:

答案 0 :(得分:2)

我肯定会选择第一个选项。拥有像存储库这样的服务类的接口很有用,但是对于像User这样的实体类,并不是那么多。

正如您所说,每次添加属性时,您还需要将属性添加到接口,这很乏味。假设您的用户类是一个没有依赖于其他类的简单类,即使没有接口也很容易测试。

相关阅读:

http://lostechies.com/jamesgregory/2009/05/09/entity-interface-anti-pattern/

  

实体上的接口是一种反模式 - 詹姆斯格雷戈里博客

Should entities implement interfaces?

答案 1 :(得分:2)

1)是的,两者都有效

3)是,属性和方法

2)一个更长的故事。简而言之,如果您有POCO类并且您100%确定您永远不会针对不允许您使用POCO的框架进行编码(例如,它坚持继承从特定于框架的基类继承的类),你可以选择第一个选项(类)。

但它并不总是有效。

例如,为实体框架代码编写Linq2SQL和其他存储库的存储库编码,您不能使用完全相同的类集。第二种(接口)方法是唯一的选择。我们已成功地在多个企业应用程序中使用它而没有任何问题。

建议 - 如果你使用接口方法,你肯定需要一个方法来创建一个空实例

public interface IUserRepository
{
    List<IUser> getAll();
    ...
    IUser CreateNew();
}

否则,存储库客户端没有其他方法可以创建具体类型的实例 - 客户端不知道该类型。但是,有些人倾向于将创建方法移动到单独的工厂类中。

答案 2 :(得分:1)

我认为您的部分困惑在于您的User类中有方法。通常,这些类型的模型类仅表示数据,而不描述行为。所以,如果你把你的方法移到更适合的地方,你的整个混乱就会消失,因为没有理由建立一个界面。

换句话说,将方法移出User类并让您的repo工作如下:

List<User> getAll();