3

I have controller class 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");
        }
    }
}

Now in method AddBindings() of NinjectDependencyResolver.cs constructor argument is hardcoded. I want read Title attribute and put to

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

I plan set this field value when user fill search Input and click to button "Search".

Can somebody help and answer how better to do that NinjectDependencyResolver can get value from ProductController?

Markus Safar
  • 6,324
  • 5
  • 28
  • 44
Stanislav Machel
  • 349
  • 2
  • 20

1 Answers1

2

You can use WithConstructorArgument(string name, Func<Ninject.Activation.IContext, object> callback) overload.

The general idea is that:

  • Get the type of the controller
  • Create the instance of that type
  • Get the Title property's value
  • Return it's value

So, the result is:

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

But, Activator.CreateInstance will need paramterless constructor to create a new instance, so add parametrless constructor to your controllers.

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

Additional detail and 2nd choice:

If we don't want to hardcode Title value during binding, then we must create instance of the controller as in the previous example, because it means that we want to get it's property value before initializing. Or you can store Titles for controller in another resource file. Then you will not need controller instance, just get controller type and then get needed value from that resource file.

But, if you wish you can also use WhenInjectedInto as:

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

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

And for storing titles in controller, you can change it to const:

public const string Title = "Bible";
Farhad Jabiyev
  • 26,014
  • 8
  • 72
  • 98