嗨,这可能是微不足道的,但我正在尝试使用接口来理解类实例化。所以下面是我的代码:
public interface IRepository
{
string GetMemberDisplayName();
}
public class Repository : IRepository
{
private readonly Manager _manager;
public Repository() {}
public Repository(string connectionName)
{
_manager = new Manager(connectionName);
}
public string GetMemberDisplayName(string ID)
{
return "FooFoo";
}
}
现在,在使用存储库类功能的另一个类中,已将其实例化,如下所示:
public class LogServiceHelper
{
readonly IRepository _alrAttendance;
readonly IRepository _alrUsers;
public LogServiceHelper()
{
_alrAttendance = new Repository("value1");
_alrUsers = new Repository("value2");
}
public string GetMemberName(string empId)
{
return _alrUsers.GetMemberDisplayName(empId);
}
}
我的问题是这是否是使用参数化构造函数实例化类的正确方法。如果是,那么第二个问题是为什么在这种情况下我们需要接口。我们可以在不创建接口的情况下直接实例化类吗?
,这就是调用参数化构造函数的方法,但不,这不是你应该做的。
正如你所拥有的,LogServiceHelper
对Repository
类有很强的依赖性,所以你是对的,接口不会给你买任何东西。但是,如果注射了它们:
public LogServiceHelper(IRepository attendanceRepo, IRepository userRepo)
{
_alrAttendance = attendanceRepo;
_alrUsers = userRepo;
}
你突然获得了抽象的好处。值得注意的是,单元测试可以在假存储库中通过,并且您可以在不更改LogServiceHelper
的情况下切换到IRepository
的另一个实现。
接下来的问题是"谁创造了Repository
具体的类?为此,我向您推荐各种DI/IoC容器,例如Autofac,Unity和NInject。
我们可以直接实例化类,而无需创建 接口?
这确实是真的,它可能没有任何问题。但是,我们接下来要解决关键问题:
- 我的代码是可测试的吗,我将如何测试这段代码?
- 我可以在不更改日志服务助手的情况下轻松更改行为吗
如果你不依赖抽象,那么不幸的是,上述问题的答案是否定的。幸运的是,有一种叫做SOLID的东西,D代表依赖注入原则。
public LogServiceHelper(IRepository alrAttendance, IRepository alrUsers)
{
_alrAttendance = alrAttendance;
_alrUsers = alrUsers;
}
因此,通过这个简单的更改,您对模块进行了解耦,突然之间,您依赖于抽象,这为设计带来了很多好处。