为了更方便地进行单元测试,我正在尝试通过将数据访问功能移动到单独的存储库类中来实现存储库模式。
我的存储库中的数据访问类:
但问题是,控制器从未被调用。
我已经将其从之前的版本更改,其中控制器负责一切。所以我所做的一切就是将数据访问移出到一个单独的类中。错误视图与之前相同。我在实现中错过了一些细节吗?
更新:
我对构造函数进行了一些修改,并且有一些问题。为什么注入到构造函数中的以下代码无法工作:
现在我可以使用构造函数注入,从而将我的ErrorController与ErrorRepository解耦:
我的存储库中的数据访问类:
public class ErrorRepository : IErrorRepository
{
public ErrorModel Errors { get; set; }
public List<ErrorModel> ErrorList { get; set; }
public List<ErrorModel> GetErrors()
{
string cs = "some path";
using (SQLiteConnection con = new SQLiteConnection(cs))
{
var listOfErrors = new List<ErrorModel>();
string stm = "SELECT * FROM Error WHERE Checked == 'False'";
con.Open();
using (SQLiteCommand cmd = new SQLiteCommand(stm, con))
{
using (SQLiteDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
listOfErrors.Add(new ErrorModel
{
Id = rdr["ID"].ToString()
});
}
rdr.Close();
ErrorList = listOfErrors;
}
}
con.Close();
}
return ErrorList;
}
}
public interface IErrorRepository
{
List<ErrorModel> GetErrors();
}
我的控制器:
public class ErrorController : Controller
{
private IErrorRepository _errorRepository;
public ErrorController(IErrorRepository errorRepository)
{
_errorRepository = errorRepository;
}
public ActionResult Error(int? page)
{
var errors = _errorRepository.GetErrors();
//// stuff for paging
int pageSize = 10;
int pageNumber = (page ?? 1); // if there is no page, return page 1
return View(errors.ToPagedList(pageNumber, pageSize));
}
}
但问题是,控制器从未被调用。
我已经将其从之前的版本更改,其中控制器负责一切。所以我所做的一切就是将数据访问移出到一个单独的类中。错误视图与之前相同。我在实现中错过了一些细节吗?
更新:
我对构造函数进行了一些修改,并且有一些问题。为什么注入到构造函数中的以下代码无法工作:
public ErrorController(IErrorRepository _errorRepository)
{
this._errorRepository = _errorRepository;
}
但是,如果我把它改成这样,控制器就会被调用,一切似乎都正常工作:
public ErrorController()
{
_errorRepository = new ErrorRepository();
}
但是最后一个例子不是一个好的做法,因为ErrorController仍然与ErrorRepository紧密耦合吗?
更新2:
我创建了这个自定义控制器工厂:
public class ControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
try
{
if (controllerType == null)
{
throw new ArgumentNullException("controllerType");
}
if (!typeof (IController).IsAssignableFrom(controllerType))
{
throw new ArgumentException(string.Format("Type requested is not a controller: {0}", controllerType.Name), "controllerType");
}
return MvcUnityContainer.Container.Resolve(controllerType) as IController;
}
catch (Exception)
{
return null;
}
}
}
public static class MvcUnityContainer
{
public static UnityContainer Container { get; set; }
}
还有这个引导类来设置所有依赖项:
public class Bootstrapper
{
public static IUnityContainer Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.RegisterType<IErrorRepository, ErrorRepository>();
MvcUnityContainer.Container = container;
return container;
}
}
然后我在 Global.asax 文件中初始化它:
// Initialise IoC container
Bootstrapper.Initialise();
// Register custom controller factory
ControllerBuilder.Current.SetControllerFactory(typeof(ControllerFactory));
现在我可以使用构造函数注入,从而将我的ErrorController与ErrorRepository解耦:
public ErrorController(IErrorRepository errorRepository)
{
this.errorRepository = errorRepository;
}
IErrorController
的 IoC?很可能因为你没有一个空的构造函数并且可能没有进行 DI 设置,所以它最终没有成功调用控制器。 - JohanErrorRepository
的实例到ErrorController
中,以满足对IErrorRepository
的依赖。使用 DI 容器,你可以注册应该被用来满足依赖的类型,容器可以创建该类型的实例并提供给控制器。而且,第二种方式与ErrorRepository
紧密耦合,应该避免,因为它无法隔离。 - mason