【问题标题】:How transfer to AddBindings() in NinjectDependencyResolver concrete type argument from MVC controller class?如何从 MVC 控制器类转移到 NinjectDependencyResolver 具体类型参数中的 AddBindings()?
【发布时间】:2016-01-30 13:19:33
【问题描述】:

我有控制器类 ProductController.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)
                );
        }
    }
}

类 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");
}

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

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

【问题讨论】:

    标签: c# .net asp.net-mvc ninject ninject.web.mvc


    【解决方案1】:

    你可以使用WithConstructorArgument(string name, Func&lt;Ninject.Activation.IContext, object&gt; callback)重载。

    总体思路是:

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

    所以,结果是:

    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";
    

    【讨论】:

    • Farhad Jabiyev,感谢您的回答和 cmets。我会尽快得到反馈。
    • 谢谢你,法哈德!我测试了您描述的第二种方法效果很好。
    • @StanislavMachel 很高兴为您提供帮助。第一个解决方案呢?
    • 你知道如何使用 Ninject 将控制器动作的参数作为参数传递给具体类型吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多