如何从 MVC 控制器 class 传输到 NinjectDependencyResolver 具体类型参数中的 AddBindings()?

How transfer to AddBindings() in NinjectDependencyResolver concrete type argument from MVC controller class?

我有控制器classProductController.cs

namespace AmazonProductAdvertisingAPI.WebUI.Controllers
{
    public class ProductController : Controller
    {
        private string _title = "Bible";
        private IProductCollection _productCollection;
        public int pageSize = 13;

        public ProductController(IProductCollection productCollection)
        {
            _productCollection = productCollection;
        }

        public string Title
        {
            get
            {
                return _title;
            }
            set
            {
                _title = value;
            }
        }

        // GET: Product
        public ActionResult List(int page = 1)
        {
            return View(_productCollection.Products
                .OrderBy(product => product.Title)
                .Skip((page - 1)*pageSize)
                .Take(pageSize)
                );
        }
    }
}

class NinjectDependencyResolver.cs

namespace AmazonProductAdvertisingAPI.WebUI.Infrastructure
{
    public class NinjectDependencyResolver : IDependencyResolver
    {
        private IKernel kernel;

        public NinjectDependencyResolver(IKernel kernelParam)
        {
            kernel = kernelParam;
            AddBindings();
        }

        public object GetService(Type serviceType)
        {
            return kernel.TryGet(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return kernel.GetAll(serviceType);
        }

        private void AddBindings()
        {
            // Create dependency here

            kernel.Bind<IProductCollection>().To<AmazonProductCollection>()
                                             .WithConstructorArgument("title", "Bible");
        }
    }
}

现在,NinjectDependencyResolver.cs 构造函数参数的方法 AddBindings() 是硬编码的。我想阅读 Title 属性并放入

private void AddBindings()
{
    // Create dependency here
    kernel.Bind<IProductCollection>().To<AmazonProductCollection>()
                                     .WithConstructorArgument("title", "here_must_be_Title_field_from_ProductController");
}

我计划在用户填写搜索输入并单击按钮时设置此字段值 "Search"。

有人可以帮助并回答 NinjectDependencyResolver 如何更好地从 ProductController 获取价值吗?

您可以使用 WithConstructorArgument(string name, Func<Ninject.Activation.IContext, object> callback) 重载。

大意是:

  • 获取控制器类型
  • 创建该类型的实例
  • 获取 Title 属性 的值
  • Return 值

所以,结果是:

kernel.Bind<IProductCollection>()
    .To<AmazonProductCollection>()
    .WithConstructorArgument(
        "title",
        ninjectContext =>
        {
            var controllerType = ninjectContext.Request
                  .ParentRequest
                  .Service;

            var controllerInstance =  Activator.CreateInstance(controllerType);

            return controllerInstance.GetType()
                .GetProperty("Title")
                .GetValue(instance);
        });

但是,Activator.CreateInstance 将需要无参数构造函数来创建新实例,因此请将无参数构造函数添加到您的控制器中。

public class ProductController : Controller
{
   ...
   public ProductController() {}
   ...
}

其他详细信息和第二个选择:

如果我们不想在绑定期间硬编码 Title 值,那么我们必须像前面的示例一样创建控制器的实例,因为这意味着我们想要获取它的 属性初始化前的值。或者您可以将控制器的 Titles 存储在另一个资源文件中。那么你将不需要控制器实例,只需获取控制器类型,然后从该资源文件中获取所需的值。

但是,如果您愿意,也可以使用 WhenInjectedInto 作为:

kernel.Bind<IProductCollection>()
    .To<AmazonProductCollection>()
    .WhenInjectedInto<ProductController>()
    .WithConstructorArgument("title", ProductController.Title);

kernel.Bind<IProductCollection>()
    .To<AmazonProductCollection>()
    .WhenInjectedInto<HomeController>()
    .WithConstructorArgument("title", HomeController.Title);

为了在控制器中存储标题,您可以将其更改为 const:

public const string Title = "Bible";