对于我的ASP.NET MVC项目,我过去非常依赖静态方法来进行数据访问,如下所示:
public class MyTable
{
public static IEnumerable<MyTable> findAll()
{
using (var connection = new SqlConnection(Provider.connString))
{
//implementation here
}
return datas;
}
public static MyTable find(guid id)
{
using (var connection = new SqlConnection(Provider.connString))
{
//implementation here
}
}
}
所以我可以在我的控制器中像这样调用它们:
var datas = MyTable.findAll();
我对此感到满意,但我怀疑我是否正在通过它进行数据访问。
现在,我试图将依赖注入仅仅用于某些学习目的,我的数据访问类是这样的:
public class MyTable
{
public IDatabaseEngine _engine = null;
public MyTable()
{
}
public MyTable(IDatabaseEngine engine)
{
_engine = engine;
}
public IEnumerable<MyTable> findAll()
{
using (var connection = _engine.getConnection())
{
//implementation here
}
return datas;
}
public MyTable find(guid id)
{
using (var connection = _engine.getConnection())
{
//implementation here
}
return data;
}
}
问题是,这意味着我必须创建一个MyTable
类的实例来调用我的控制器上的数据访问方法,如下所示:
var table = new MyTable(new MSSQLEngine(provider.connString));
var datas = table.findAll();
我要非常缺乏经验来解决这个问题,或者我做错了,我觉得在为我需要的每个数据访问实例化对象时感到不舒服。
我的问题是
答案 0 :(得分:1)
您的问题的答案:
要正确使用DI,首先需要将MyTable
类解压缩到接口中,然后将该接口注入控制器。
public interface IMyTable
{
IEnumerable<MyTable> findAll();
// other methods
}
public class MyTable : IMyTable
{
// your implementation
}
然后你的控制器应该是这样的:
public class YourController : Controller
{
private IMyTable myTable;
public YourController(IMyTable myTable)
{
this.myTable = myTable;
}
public ActionResult YourAction()
{
var result = myTable.findAll();
// ...
}
}
我个人使用Castle Windsor作为IoC容器,here is an example在ASP.NET MVC应用程序中使用Castle Windsor
答案 1 :(得分:1)
虽然DI在某些情况下很酷,但在大多数情况下是过度工程!
我解释一下。如何创建静态方法。只需在方法前放置“静态”。你可以通过调用Class.Method()轻松调用它。此外,它对系统有效,因为该方法只创建一次。
亲:效率很高。 缺点:不可变
虽然DI,你可能需要一些容器,然后是一个接口,你可以添加一个类,任何实现该接口的类。而且,在代码的某些部分,您将需要创建该类的实例(ergo是该方法的新实例)。
亲:是可变的 缺点:效率不高,其冗长。
答案 2 :(得分:0)
依赖注入只是一种在实例字段中存储依赖关系的技术,因此您基本上是在MyTable
实现中正确执行。
如果要在控制器的构造函数中获取IDatabaseEngine
的实例,如果要在控制器的测试中模拟数据库引擎,则可以从依赖注入中受益。您仍然需要一种在应用程序中注入实例的方法。至于现在,您正在控制器中创建具体类MSSQLEngine
的实例,因此没有任何好处。
在这种情况下使用静态方法并不好,因为在您决定实现数据库无关的测试时,您需要重构使用实例。从最小的测试设置开始是一个很好的做法,因此您可以在项目生命周期的早期阶段实现可测试性。我建议在你的代码库变大之前做这个很难的部分。
了解如何在控制器中注入IDatabaseEngine
的实例,并编写一个利用依赖注入的最小测试。大多数MVC框架允许设置作为工厂的IoC容器。在测试中,您需要使用一些模拟实现或模拟框架(如Moq)来组成IDatabaseEngine
的实例。