【问题标题】:How pass parameters of controller's action to Ninject concrete type?如何将控制器动作的参数传递给 Ninject 具体类型?
【发布时间】:2016-02-01 18:35:55
【问题描述】:

我有 ProductController.cs

    namespace AmazonProductAdvertisingAPI.WebUI.Controllers
    {
        public class ProductController : Controller
        {

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

            public static string Title
            {
                get
                {
                    return _title;
                }
                set
                {
                    _title = value;
                }
            }
            public static int PageNumber
            {
                get
                {
                    return _pageNumber;
                }
                set
                {
                    _pageNumber = value;
                }
            }
            public static int ItemsPerPage
            {
                get
                {
                    return _itemsPerPage;
                }
                set
                {
                    _itemsPerPage = value;
                }
            }
            // GET: Product
            public ActionResult List(int page = 1, string search = null)
            {

                ProductListViewModel model = new ProductListViewModel
                {
                    Products = _productCollection.Products
                                                 .OrderBy(product => product.Title)
                                                 .Skip((page - 1) * pageSize)
                                                 .Take(pageSize),
                    PagingInfo = new PagingInfo
                    {
                        CurrentPage = page,
                        ItemsPerPage = pageSize,
                        TotalItems = _productCollection.Products.Count()
                    }
                };
                return View(model);
            }
        }
    }

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>()
                                                 .WhenInjectedInto<ProductController>()
                                                 .WithConstructorArgument("title", ProductController.Title)
                                                 .WithConstructorArgument("pageNumber", ProductController.PageNumber)
                                                 .WithConstructorArgument("itemsPerPage", ProductController.ItemsPerPage);
            }
        }
    }

AmazonProductCollection 类有构造函数:

public AmazonProductCollection(string title, int pageNumber, int itemsPerPage)

我希望 AmazonProductCollection 从产品控制器的操作列表参数中获取自己的参数,因为当用户填写 TextBoxt 并单击 html-view 表单中的“搜索”按钮时,它会获取其中的一些参数。例如,我想使用操作列表中的参数字符串“search”并作为构造函数参数“title”传输到 AmazonProductCollection。

我读了这篇文章:How to pass parameters to a transient object created by Ninject?,但我不明白如何在我的情况下创建相同的东西。

有人可以帮我处理 Ninject 吗?

【问题讨论】:

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


    【解决方案1】:

    一种解决方案是使用工厂。

    工厂界面如下所示:

    public interface IAmazonProductCollectionFactory
    {
        AmazonProductCollection Create(string title, int pageNumber, int itemsPerPage);
    }
    

    这样的接口将存在于控制器所在的同一个项目中(MVC 项目)。

    这种工厂的实现如下所示:

    public class AmazonProductCollectionFactory : IAmazonProductCollectionFactory
    {
        private readonly IResolutionRoot m_ResolutionRoot;
    
        public AmazonProductCollectionFactory (IResolutionRoot resolution_root)
        {
            m_ResolutionRoot = resolution_root;
        }
    
        public AmazonProductCollection Create(string title, int pageNumber, int itemsPerPage)
        {
            return resolution_root.Get<AmazonProductCollection>(
                new ConstructorArgument("title", title),
                new ConstructorArgument("pageNumber", pageNumber),
                new ConstructorArgument("itemsPerPage", pageNumber));
        }
    }
    

    AmazonProductCollectionFactory 将存在于Composition Root 项目中。在您的情况下,这可能是同一个 MVC 项目。请注意,拥有依赖于IResolutionRoot 的工厂,除了组合根之外的任何地方都是is considered an anti-pattern 的服务位置示例。

    现在,您需要将IAmazonProductCollectionFactory 注入ProductController 的构造函数中,而不是IProductCollection,并让List 操作使用它来创建AmazonProductCollection 实例,如下所示:

    var productCollection = factory.Create(...);
    

    其中factory 是您用来存储注入的IAmazonProductCollectionFactory 的实例变量的名称。

    别忘了在 Ninject 容器中注册 IAmazonProductCollectionFactory

    请注意,您应该考虑创建符合List 操作要求的服务。例如,您可以将整个搜索逻辑包装在知道如何进行搜索的服务中,并让此类服务担心通过抽象工厂创建AmazonProductCollection。然后,不是将工厂注入控制器,而是将服务注入控制器。

    【讨论】:

    • 把这个工厂类放在哪里更好?在域项目或 mvc 中?你能指定哪个文件夹更好地用于会议吗?
    • 工厂应该存在于组合根目录中。这尽可能靠近应用程序入口点。 MVC 项目是一个合适的地方。你在哪里有NinjectDependencyResolver 课程?你可以把工厂放在这个类的同一个文件夹中。
    • 谢谢!你的回答对我有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-09
    • 2020-08-12
    • 2023-03-24
    • 1970-01-01
    • 2011-02-18
    • 1970-01-01
    相关资源
    最近更新 更多