Inject a dependency into a custom model binder and using InRequestScope using Ninject

前端 未结 3 1332
无人及你
无人及你 2020-12-03 22:53

I\'m using NInject with NInject.Web.Mvc.

To start with, I\'ve created a simple test project in which I want an instance of IPostRepository to be shared

3条回答
  •  佛祖请我去吃肉
    2020-12-03 23:27

    I eventually managed to solve it with a factory as suggested. However, I just could not figure out how to accomplish this with Ninject.Extensions.Factory which is what I would've preferred. Here is what I ended up with:

    The factory interface:

    public interface IPostRepositoryFactory
    {
        IPostRepository CreatePostRepository();
    }
    

    The factory implementation:

    public class PostRepositoryFactory : IPostRepositoryFactory
    {
        private readonly string key = "PostRepository";
    
        public IPostRepository CreatePostRepository()
        {
            IPostRepository repository;
    
            if (HttpContext.Current.Items[key] == null)
            {
                repository = new PostRepository();
                HttpContext.Current.Items.Add(key, repository);
            }
            else
            {
                repository = HttpContext.Current.Items[key] as PostRepository;
            }
    
            return repository;
        }
    }
    

    The Ninject module for the factory:

    public class PostRepositoryFactoryModule : NinjectModule
    {
        public override void Load()
        {
            this.Bind().To();
        }
    }
    

    The custom model binder:

    public class CustomModelBinder : DefaultModelBinder
    {
        private IPostRepositoryFactory factory;
    
        public CustomModelBinder(IPostRepositoryFactory factory)
        {
            this.factory = factory;
        }
    
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            IPostRepository repository = factory.CreatePostRepository();
    
            repository.Add("Model binder");
    
            return base.BindModel(controllerContext, bindingContext);
        }
    }
    

    The controller:

    public class HomeController : Controller
    {
        private IPostRepository repository;
    
        public HomeController(IPostRepositoryFactory factory)
        {
            this.repository = factory.CreatePostRepository();
        }
    
        public ActionResult Index(string whatever)
        {
            repository.Add("Action method");
    
            return View(repository.GetList());
        }
    }
    

    Global.asax to wire up the custom model binder:

    protected override void OnApplicationStarted()
    {
        AreaRegistration.RegisterAllAreas();
    
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    
        ModelBinders.Binders.Add(typeof(string), kernel.Get());
    }
    

    Which in my view, gave me the desired output of:

    Model binder
    Action method

提交回复
热议问题