如何将控制器操作的参数传递给 Ninject 混凝土类型

本文关键字:Ninject 混凝土 类型 参数传递 控制器 操作 | 更新日期: 2023-09-27 18:32:50

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

类具有构造函数:

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

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

我读了这篇文章:如何将参数传递给Ninject创建的瞬态对象?,但我不明白在我的情况下如何创建相同的东西。

有人可以帮助我注射吗?

如何将控制器操作的参数传递给 Ninject 混凝土类型

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

工厂界面如下所示:

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将位于合成根项目中。在您的情况下,这可能是同一个 MVC 项目。请注意,拥有依赖于除组合根之外IResolutionRoot任何地方的工厂是服务位置的一个例子,它被认为是反模式。

现在,您需要将

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

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

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

不要忘记向 Ninject 容器注册IAmazonProductCollectionFactory

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