如何将控制器动作的参数传递给 Ninject 具体类型?
How pass parameters of controller's action to Ninject concrete type?
我有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 class 有构造函数:
public AmazonProductCollection(string title, int pageNumber, int itemsPerPage)
我希望 AmazonProductCollection 从 Product 控制器的操作列表参数中获取自己的参数,因为其中一些参数是在用户填写 TextBoxt 并单击 html-view 表单中的按钮 "Search" 时获取的。例如,我想使用操作列表中的参数字符串 "search" 并将其作为构造函数参数 "title".
传输到 AmazonProductCollection
我读了这个 post:How to pass parameters to a transient object created by 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
会住在 Composition Root project. In your case, this is probably the same MVC project. Please note that having such factory that depends on IResolutionRoot
any place except for the composition root is an example of service location which is considered an anti-pattern 里面。
现在,您需要将 IAmazonProductCollectionFactory
注入 ProductController
的构造函数,而不是 IProductCollection
,让 List
操作使用它来创建一个 AmazonProductCollection
像这样的实例:
var productCollection = factory.Create(...);
其中 factory
是您用来存储注入的实例变量的名称 IAmazonProductCollectionFactory
。
不要忘记在 Ninject 容器中注册 IAmazonProductCollectionFactory
。
请注意,您应该考虑创建符合 List
操作要求的服务。例如,您可以将整个搜索逻辑包装在一个知道如何进行搜索的服务中,并让该服务负责通过抽象工厂创建 AmazonProductCollection
。然后,不是将工厂注入控制器,而是将服务注入控制器。
我有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 class 有构造函数:
public AmazonProductCollection(string title, int pageNumber, int itemsPerPage)
我希望 AmazonProductCollection 从 Product 控制器的操作列表参数中获取自己的参数,因为其中一些参数是在用户填写 TextBoxt 并单击 html-view 表单中的按钮 "Search" 时获取的。例如,我想使用操作列表中的参数字符串 "search" 并将其作为构造函数参数 "title".
传输到 AmazonProductCollection我读了这个 post:How to pass parameters to a transient object created by 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
会住在 Composition Root project. In your case, this is probably the same MVC project. Please note that having such factory that depends on IResolutionRoot
any place except for the composition root is an example of service location which is considered an anti-pattern 里面。
现在,您需要将 IAmazonProductCollectionFactory
注入 ProductController
的构造函数,而不是 IProductCollection
,让 List
操作使用它来创建一个 AmazonProductCollection
像这样的实例:
var productCollection = factory.Create(...);
其中 factory
是您用来存储注入的实例变量的名称 IAmazonProductCollectionFactory
。
不要忘记在 Ninject 容器中注册 IAmazonProductCollectionFactory
。
请注意,您应该考虑创建符合 List
操作要求的服务。例如,您可以将整个搜索逻辑包装在一个知道如何进行搜索的服务中,并让该服务负责通过抽象工厂创建 AmazonProductCollection
。然后,不是将工厂注入控制器,而是将服务注入控制器。