我正在开发一个服务,它通过存储库执行数据库操作。在服务中,我实例化了需要构造函数中的数据库上下文的存储库。我想知道上下文是否应该传递到服务中,或者下面的代码是否正常。或者将Repository对象传递给服务以供它使用会更好吗?使用Service类时,UI代码应该是什么样的?
public class Service
{
private IRepository<WWW> _repository;
public Service()
{
_repository = new Repository<WWW>(new DBContext());
}
public WWW GetWWW(int wwwID)
{
return _repository.Get(x => x.WWWID == wwwID).FirstOrDefault();
}
public void AddWWW(WWW www)
{
_repository.Add(www);
}
public void DeleteWWWByID(int wwwID)
{
_repository.Delete(x => x.WWWID == wwwID);
}
public void SaveChanges()
{
_repository.SaveChanges();
}
}
答案 0 :(得分:2)
事实上,最好通过服务的构造函数将存储库传递给服务,如下所示:
public class Service
{
private readonly IRepository<WWW> _repository;
public Service(IRepository<WWW> repository)
{
_repository = repository;
}
/* the rest is unchanged */
}
简而言之,表示UI的类将依赖于Service,因此代码可能如下所示:
public class UIClass : BaseClassDictatedByCurrentUIFramework
{
private readonly Service _service;
public UIClass(Service service)
{
_service = service;
}
/* UI code that will eventually call methods on the service */
}
接下来要做的是配置一个Inversion of Control容器,该容器将知道如何解析IRepository的实例(并在需要时为它们提供适当的DataContext实例)。
例如,如果我们的UI代码是MVC3控制器,我们会告诉容器解析此控制器的实例。这就是:
容器注意到对Service
的依赖(在构造函数中)并尝试解决它。
由于Service
是一个具体类,容器将尝试解析它
注意对IRepository<WWW>
的依赖。
IRepository
的分辨率,因为这是一个界面,要求容器先前已设置为“知道”当它被要求提供它的实例时要返回的内容。通常,这只是接口与其具体实现之间的映射。在我们的例子中,具体实现是Repository<WWW>
,容器还负责“知道”如何为它实例化所需的DataContext
实例(这也必须事先配置)
拥有一个存储库实例,然后容器能够首先正确地实例化Service
,然后是控制器类。
请注意,具体类的自动解析是一个并非所有IoC容器都具有的功能;有些需要显式配置才能这样做。
除此之外,我认为Service
类在你的案例中没有增加太多价值。它仅包含对存储库实现的方法的委派。在这种情况下,让UI直接依赖IRepository<WWW>
并简单地删除Service
类可能会更好。
但是,如果这个Service
类只是一个示例,并且在您的实际项目中它实现了实际的业务规则,则应该保留它。
更新:如何解决ASP.Net Webforms中的依赖关系
上面介绍的示例是理想的依赖注入方案。它可以在ASP.NET MVC中工作,其中BaseClassDictatedByCurrentUIFramework将是Controller
- 在这种情况下,框架允许我们控制实例化控制器的组件,因此我们可以在构造函数中注入我们自己的依赖项。
然而,ASP.Net WebForms不是一个非常友好的框架。它要求每个Page
都需要一个默认的构造函数,这使得所有构造函数注入的想法都不合适。
在这种情况下,一种可能的解决方案是以下妥协:
Page
类中将依赖关系声明为private readonly
字段,但构造函数将没有相应的参数(它根本没有参数)请注意,这种方法需要规范 - 在构造函数解析其他组件的其他地方容易使用容器。这种方法称为服务定位器,它被认为是反模式(http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx),因此应该避免使用。
答案 1 :(得分:0)
我建议一次性依赖倒置。就个人而言,我认为这不是你是否应该将服务传递给DBContext,而是你应该将服务传递给存储库本身。