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 constructorparameterize 所以当用户请求像 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());