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

时间:2016-01-30 13:19:33

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

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

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

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

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

1 个答案:

答案 0 :(得分:2)

您可以使用WithConstructorArgument(string name, Func<Ninject.Activation.IContext, object> 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值,那么我们必须像前面的示例一样创建控制器的实例,因为这意味着我们想要获得它的属性初始化之前的值。或者,您可以将控制器的Title存储在另一个资源文件中。然后你将不需要控制器实例,只需获取控制器类型,然后从该资源文件中获取所需的值。

但是,如果您愿意,也可以使用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";