2010-06-03 66 views
4

我有一個可以在不同提供程序中搜索的搜索表單。 我開始了由具有基本控制器根據查詢字符串/派生控制器注入不同的存儲庫並根據控制器類型注入存儲庫/ ASP.NET MVC

public SearchController : Controller 
{ 

    protected readonly ISearchService _searchService 

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

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

} 

而且孩子控制器

TwitterController : SearchController 
{ 
    ... 
} 

NewsController : SearchController 
{ 
    ... 
} 

我用StructureMap插入我的控制器中的所有依賴。通過這種設置,我可以根據實例化控制器的類型更改SearchService。

x.For<ISearchService>().ConditionallyUse(o => 
     { 
      o.TheDefault.Is.OfConcreteType<NewsSearchService>(); 

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

      ... 

     }); 

,即使讓我爲每個控制器設置不同的意見,(只是把相應的文件夾(推特,新聞...)和父控制器仍然是處理所有的搜索,用一個簡單的

return View(results) 

這顯示特定嘰嘰喳喳正確的觀點,新聞,或其他

現在很冷靜,看起來很棒,我一個單一的形式和不同的視圖顯示在同一頁面上的標籤。這就是它這種方法開始變得複雜表單必須發佈到/ Twitter在Twitter中進行搜索,以/ News在新聞中搜索...這意味着我應該根據哪個選項卡更改表單的操作參數,並在表單返回時顯示正確的選項卡在..的網址?瘋狂如下。

如果你已經建立了這樣的東西,或知道什麼是最好的辦法,請大家指教。

現在我想我會有更少的痛苦使用窗體中的參數併發布到單個控制器。我正在考慮根據此參數注入正確的SearchService。最好的方法是什麼?我想用一個模型綁定的,

所以,我有我的ActionMethod看起來像這樣的:

public ActionResult Search(ISearchService service, Query query) 
{ 
    var results = service.Find(query); 
} 

但我認爲需要做這樣的呼籲在ModelBinder的

ObjectFactory.GetInstance(...); 

基於描述使用哪個提供程序的querystring參數,對我來說看起來並不高雅。 。我覺得卡住,幫助:(

回答

1

我想弄清楚如何使用抽象工廠模式,並仍然讓結構映射解決我的組件的所有依賴關係。

我相信這是我要實現它的方式,但如果有人會閱讀本文,我會在此提交以獲得一些反饋。

正如在前面的回答中所解釋的,我不想根據抽象工廠中需要的提供程序構建整個對象圖。

即:

class StatServiceFactory : IStatServiceFactory 
{ 
    public IStatService Create(string provider) 
    { 
     switch(provider) 
     { 
      case "blog": 
       return new StatService(IFacetRepository,ISearchManager,IConfigManager,BooleanQueryBuilder); 
         //How to resolve the Config, the SearchManager, and BooleanQueryBuilder? 
         //Add more abstract factories? It starts to get messy in my opinion... 
     } 
    } 

} 

什麼我可以做的是有抽象工廠用我的容器創建取決於參數我的搜索管理者的一個實例(從查詢字符串來在我的情況)

Structuremap允許以這種方式創建命名實例:

x.For<ISearchManager>().Use<AbcSearchManager>().Named("Abc"); 
x.For<ISearchManager>().Use<DefSearchManager>().Named("Def"); 

我需要一種方法在我的抽象工廠中注入容器。 我可能將容器包裝在一個像這樣定義的包裝中。這會阻止我將Structuremap泄漏到我的項目中。我不需要更多的是抽象工廠內的那些2個功能無論如何,但它是沒有必要的:

public interface IContainerWrapper 
{ 
    object GetInstance<T>(); 
    object GetNamedInstance<T>(string key); 
} 

和實現:

public class ContainerImpl : IContainerWrapper 
{ 
    private readonly Container _container 
    public ContainerImpl(Container container) 
    { 
      _container = container; 
    } 

    ... 
} 

和設置StructureMap解決依賴於我的抽象工廠一樣, :

x.For<IContainer>.Use(new ContainerImpl(this)); 
x.For<IFactory>.Use<Factory>() 

我廠是那麼簡單得多,並會創造我的實例這樣的:

public class SearchmanagerFactory 
{ 
    private readonly IContainerWrapper _container; 

    public SearchmanagerFactory(IContainerProvider containerProvider) 
    { 
     _container = containerProvider; 
    } 

    public ISearchManager Create(string provider) 
    { 
     //eed to handle the bad input for provider. 
     return (ISearchManager) 
      _container.Resolve<ISearchManager>(provider); 
    } 
} 

這看起來很乾淨:)。 想法?

6

每當你需要改變基於一個運行時間值的依賴,Abstract Factory是通用的解決方案

而是注入ISearchService到您的控制器,注入的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); 
} 
+0

Erf,實際上這並不適合。我會有很多工廠,因爲我的SearchService具有更多的依賴關係,這些依賴關係也可以通過結構圖來解決。我會通過使用這個工廠失去所有的好處,最終我會手動完成結構圖爲我所做的所有工作。 – 2010-06-03 13:25:31

+0

看到我的其他建議。你怎麼看? – 2010-06-03 13:36:04

+0

這真的是我應該去的方式嗎?那隻會刪除我的IOC的所有用途......並且我會根據抽象工廠中的一個參數手動連接我的所有成員? – 2010-06-04 14:03:32

0

這比解釋爲什麼AbstractFactory看起來複雜的答案更廣泛的評論。下面是一些看起來與現實更近:

class StatServiceFactory : IStatServiceFactory 
{ 
    public IStatService Create(string provider) 
    { 
     switch(provider) 
     { 
      case "blog": 
       return new StatService(IFacetRepository,ISearchManager,IConfigManager,BooleanQueryBuilder); 
          //How to resolve the Config, the SearchManager, and BooleanQueryBuilder? 
          //Add more abstract factories? It starts to get messy in my opinion... 
     } 
    } 
} 

的FacetRepository爲任何供應商相同,但SearchManager的變化,CONFIGMANAGER變化,以及BooleanQueryBuilder與不同實施不同的提供一個抽象類(因爲每個API都沒有在他們的查詢中使用相同的關鍵字)所有這些依賴關係目前都由結構圖根據控制器的類型來解析。

我真的想在這裏保留StructureMap的好處,而不是一直使用工廠,爲每個不同的部分。

請在我的問題結尾處查看我的編輯以獲取對我的問題的其他建議。

相關問題