ASP.Net MVC 中的参数化控制器 Ctor
Parameterized controller Ctor in ASP.Net MVC
我是 MVC 新手。所以我正在阅读一篇关于 repository design pattern
的文章,有一件事出现在我眼前,但不清楚。这是代码...先看代码。
public interface IUsersRepository
{
public User GetUser(int id);
}
然后实施它:
public class UsersRepository: IUsersRepository
{
private readonly string _connectionString;
public UsersRepository(string connectionString)
{
_connectionString = connectionString;
}
public User GetUser(int id)
{
// Here you are free to do whatever data access code you like
// You can invoke direct SQL queries, stored procedures, whatever
using (var conn = new SqlConnection(_connectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT id, name FROM users WHERE id = @id";
cmd.Parameters.AddWithValue("@id", id);
using (var reader = cmd.ExecuteReader())
{
if (!reader.Read())
{
return null;
}
return new User
{
Id = reader.GetInt32(reader.GetOrdinal("id")),
Name = reader.GetString(reader.GetOrdinal("name")),
}
}
}
}
}
然后您的控制器可以使用此存储库:
public class UsersController: Controller
{
private readonly IUsersRepository _repository;
public UsersController(IUsersRepository repository)
{
_repository = repository;
}
public ActionResult Index(int id)
{
var model = _repository.GetUser(id);
return View(model);
}
}
查看控制器代码。当用户请求像 Users\index
这样的页面时,将调用此操作 public ActionResult Index(int id){}
我的问题是此方法将如何工作 _repository.GetUser(id); ?
因为当 ctor
UsersController()
将被调用那么存储库实例将如何传递到那里?
我的问题是,如果 class 有 parameterize
构造函数,那么当我们需要创建那个 class 的实例时,我们需要传递参数值。
在这种情况下 controller constructor
是 parameterize
所以当用户请求像 Users\index
这样的页面时,控制器构造函数将被调用,但参数将如何传递到那里...... .......我不清楚。
请帮助我理解。谢谢
这项工作可以使用 Dependency Injection(DI) framework 完成。
DI - 消除了我们 class 感兴趣的(消费者 class)所依赖的其他对象实例的直接创建和生命周期管理的责任(在 UML 意义上) .这些实例被传递给我们的消费者 class,通常作为构造函数参数或通过 属性 设置器(依赖对象实例化和传递给消费者 class 的管理通常由反转执行控制 (IoC) 容器,但这是另一个话题)。
更多详情可以阅读文章:ASP.NET MVC 4 Dependency Injection.
另外,我建议您阅读 Pro ASP.NET MVC by Adam Freeman, that describes very well work with DI container such as Ninject.
这本书
请参阅 What is dependency injection?
我举个小例子:
我们创建了两个构造函数,第一个是不带参数的单元测试:
public BaseApiController()
{
repository = unitOfWork.EFRepository<T>();
}
第二个带有依赖注入的构造函数:
public BaseApiController(IRepository<T> repository)
{
this.repository = repository;
}
然后为了使用像 Ninject 这样的 DI 容器,我们需要创建和配置控制器工厂:
public class NinjectControlFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControlFactory()
{
//create container
ninjectKernel = new StandardKernel();
AddBindings();
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null
? null
: (IController)ninjectKernel.Get(controllerType);
}
private void AddBindings()
{
//congif container
ninjectKernel.Bind(typeof(IRepository<>)).To(typeof(EFRepository<>));
}
}
最后我们必须在 Global.asax 文件的 Application_Start()
中注册容器:
ControllerBuilder.Current.SetControllerFactory(new NinjectControlFactory());
我是 MVC 新手。所以我正在阅读一篇关于 repository design pattern
的文章,有一件事出现在我眼前,但不清楚。这是代码...先看代码。
public interface IUsersRepository
{
public User GetUser(int id);
}
然后实施它:
public class UsersRepository: IUsersRepository
{
private readonly string _connectionString;
public UsersRepository(string connectionString)
{
_connectionString = connectionString;
}
public User GetUser(int id)
{
// Here you are free to do whatever data access code you like
// You can invoke direct SQL queries, stored procedures, whatever
using (var conn = new SqlConnection(_connectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT id, name FROM users WHERE id = @id";
cmd.Parameters.AddWithValue("@id", id);
using (var reader = cmd.ExecuteReader())
{
if (!reader.Read())
{
return null;
}
return new User
{
Id = reader.GetInt32(reader.GetOrdinal("id")),
Name = reader.GetString(reader.GetOrdinal("name")),
}
}
}
}
}
然后您的控制器可以使用此存储库:
public class UsersController: Controller
{
private readonly IUsersRepository _repository;
public UsersController(IUsersRepository repository)
{
_repository = repository;
}
public ActionResult Index(int id)
{
var model = _repository.GetUser(id);
return View(model);
}
}
查看控制器代码。当用户请求像 Users\index
这样的页面时,将调用此操作 public ActionResult Index(int id){}
我的问题是此方法将如何工作 _repository.GetUser(id); ?
因为当 ctor
UsersController()
将被调用那么存储库实例将如何传递到那里?
我的问题是,如果 class 有 parameterize
构造函数,那么当我们需要创建那个 class 的实例时,我们需要传递参数值。
在这种情况下 controller constructor
是 parameterize
所以当用户请求像 Users\index
这样的页面时,控制器构造函数将被调用,但参数将如何传递到那里...... .......我不清楚。
请帮助我理解。谢谢
这项工作可以使用 Dependency Injection(DI) framework 完成。
DI - 消除了我们 class 感兴趣的(消费者 class)所依赖的其他对象实例的直接创建和生命周期管理的责任(在 UML 意义上) .这些实例被传递给我们的消费者 class,通常作为构造函数参数或通过 属性 设置器(依赖对象实例化和传递给消费者 class 的管理通常由反转执行控制 (IoC) 容器,但这是另一个话题)。
更多详情可以阅读文章:ASP.NET MVC 4 Dependency Injection.
另外,我建议您阅读 Pro ASP.NET MVC by Adam Freeman, that describes very well work with DI container such as Ninject.
这本书
请参阅 What is dependency injection?
我举个小例子:
我们创建了两个构造函数,第一个是不带参数的单元测试:
public BaseApiController()
{
repository = unitOfWork.EFRepository<T>();
}
第二个带有依赖注入的构造函数:
public BaseApiController(IRepository<T> repository)
{
this.repository = repository;
}
然后为了使用像 Ninject 这样的 DI 容器,我们需要创建和配置控制器工厂:
public class NinjectControlFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControlFactory()
{
//create container
ninjectKernel = new StandardKernel();
AddBindings();
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null
? null
: (IController)ninjectKernel.Get(controllerType);
}
private void AddBindings()
{
//congif container
ninjectKernel.Bind(typeof(IRepository<>)).To(typeof(EFRepository<>));
}
}
最后我们必须在 Global.asax 文件的 Application_Start()
中注册容器:
ControllerBuilder.Current.SetControllerFactory(new NinjectControlFactory());