asp.net-mvc - 根据查询字符串/派生 Controller 注入(inject)不同的存储库,并根据 Controller 类型/ASP.NET MVC 注入(inject)存储库

标签 asp.net-mvc design-patterns dependency-injection

我有一个搜索表单,可以在不同的提供商中搜索。
我从拥有一个基本 Controller 开始

public SearchController : Controller
{

    protected readonly ISearchService _searchService

    public SearchController(ISearchService searchService)
    {
        _searchService= searchService;
    }

    public ActionResult Search(...)
    {
        // Use searchService to query and return a view.
    }

}

和子 Controller
TwitterController : SearchController
{
    ...
}

NewsController : SearchController
{
    ...
}

我使用 StructureMap 将我所有的依赖项插入到 Controller 中。通过这个设置,我能够根据实例化 Controller 的类型更改 SearchService。
x.For<ISearchService>().ConditionallyUse(o =>
      {
            o.TheDefault.Is.OfConcreteType<NewsSearchService>();

            o.If(c => c.ParentType == typeof(TwitterController))
             .ThenIt.Is.OfConcreteType<TwitterSearchService>();

             ...

      });

这甚至允许我为每个 Controller 设置不同的 View (只需放置相应的文件夹(Twitter、News...),并且父 Controller 仍在处理所有搜索,只需一个简单的
return View(results) 

显示特定于 twitter、新闻或其他的正确 View

现在这很酷而且看起来很棒,我使用了一个表单,并且不同的 View 显示在同一页面上的选项卡中。这就是这种方法开始变得复杂的地方。表单必须发布到/Twitter 才能在 Twitter 中搜索,到/News 才能在新闻中搜索......这意味着我应该根据我所在的选项卡更改表单的操作参数,并在表单返回时显示正确的选项卡取决于.. 网址?疯狂随之而来。

如果您已经构建了这样的东西或者知道什么是最好的方法,欢迎提出建议。

现在我认为使用表单中的参数并发布到单个 Controller 会减轻痛苦。我正在考虑根据此参数注入(inject)正确的 SearchService 。最好的方法是什么?我想过使用模型活页夹,

所以我的 ActionMethod 看起来像这样:
public ActionResult Search(ISearchService service, Query query)
{
    var results = service.Find(query);
}

但我认为需要在 ModelBinder 中进行这样的调用
ObjectFactory.GetInstance(...);

基于描述要使用哪个提供程序的查询字符串参数,这对我来说似乎并不优雅。我觉得卡住了,帮助:(。

最佳答案

每当您需要根据运行时值改变依赖关系时,Abstract Factory是一般的解决方案。

不要将 ISearchService 注入(inject)到 Controller 中,而是注入(inject) ISearchServiceFactory:

public SearchController : Controller 
{ 
    private readonly ISearchServiceFactory searchServiceFactory;

    public SearchController(ISearchServiceFactory searchServiceFactory) 
    { 
        if (searchServiceFactory == null)
        {
            throw new ArgumentNullException("searchServiceFactory");
        }

        this.searchServiceFactory = searchServiceFactory; 
    } 

    public ActionResult Search(...) 
    { 
        // Use searchServiceFactory to create an ISearchService based on
        // run-time values, and use it to query and return a view. 
    } 
} 

我并不完全清楚您需要更改哪个运行时值,但假设它是查询,ISearchServiceFactory 可能定义如下:
public interface ISearchServiceFactory
{
    ISearchService Create(Query query);
}

关于asp.net-mvc - 根据查询字符串/派生 Controller 注入(inject)不同的存储库,并根据 Controller 类型/ASP.NET MVC 注入(inject)存储库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2965824/

相关文章:

java - Java swing MVC 与 Android 设计模式的比较

java - 服务类应该在java中是单例的吗?

design-patterns - 为什么在 Ruby、Python 或 PHP 中看不到 MVP 和 MVVM 模式?

php - 常量是否与全局变量和单例一样邪恶?

c++依赖注入(inject)来测试类系统调用的类

asp.net - 为什么 MVC4 Razor 布局文件中无法识别 @Scripts 和 @Styles 命令?

javascript - 在javascript中声明可观察到的动态 knockout

javascript - Angular 2 - 如何使用其他组件作为服务并获取其数据

c# - 是否可以在每个用户的基础上设置 ASP.NET Owin 安全 cookie 的 ExpireTimeSpan?

c# - 在 Code First Entity Framework (C# ASP.NET MVC 3) 中指定除 dbo 之外的 SQL 用户名