1

我不太清楚如何實現這一點,還是最好的策略是什麼,基本上我有一個(MVC)控制器工廠類 - 使用IoC容器來註冊和解析類型

public TestController(IService1 service1, IService2 service2,...) 
{ } 

(在時刻只有2個參數,但可能會增加)。

我的想法是,我會創建一個服務工廠類,因此不是每個服務的參數,我們可以代替有一個工廠,然後得到什麼服務,我們需要

private IService1 _service1; 
public TestController(IServiceFactory serviceFactory) 
{ 
    // this could also be called from a separate action, 
    // so we only get it when we need it 
    _service1 = serviceFactory.Get<IService1>(); 
} 

現在我的服務工廠實現是有點廢話,只是有本質上我是緩存所有註冊服務的字典和類型:

/// <summary> 
/// Service factory class 
/// </summary> 
/// <remarks> 
/// Only one instance of this class should be created during the lifetime of the application 
/// </remarks> 
public class ServiceFactory : IServiceFactory 
{ 
    /// <summary> 
    /// Locking object 
    /// </summary> 
    private static readonly object _lock = new object(); 

    /// <summary> 
    /// Collection of mappings 
    /// </summary> 
    private IDictionary<string, Func<IService>> _mappings; 

    /// <summary> 
    /// Default constructor 
    /// </summary> 
    public ServiceFactory() 
    { 
     _mappings = new Dictionary<string, Func<IService>>(); 
     registerMappings(); 
    } 

    /// <summary> 
    /// Get a service from the factory 
    /// </summary> 
    public T GetService<T>() where T : IService 
    { 
     if (_mappings.Count == 0) 
      throw new InvalidOperationException("There are no mappings"); 

     lock (_lock) 
     { 
      var typeName = typeof(T).Name; 
      if (_mappings.ContainsKey(typeName)) 
       return (T)_mappings[typeName](); 

      return default(T); 
     } 
    } 

    /// <summary> 
    /// Register the mappings needed for this service factory 
    /// </summary> 
    private void registerMappings() 
    { 
     register<IService1>(() => new Service1()) 
      .register<IService2>(() => new Service2()) 
      . 
      . 
      .register<IServiceN>(() => new ServiceN()); 
    } 

    /// <summary> 
    /// Register the service classes 
    /// </summary> 
    private ServiceFactory register<T>(Func<IService> mapping) where T : IService 
    { 
     var type = typeof(T).Name; 
     if (!_mappings.ContainsKey(type)) 
      _mappings.Add(type, mapping); 

     return this; 
    } 
} 

我的問題是,我可以在維修廠使用IoC容器,讓它處理註冊和類型的解決?這是一個好方法嗎?

或者我可以有一個更基本的問題,我需要一個服務工廠,我應該使用嗎?

這僅僅是因爲我的MVC控制器需要重構,即我可以嘗試和堅持一個控制器爲每個服務一個簡單的事情?

只是想在最好的辦法是什麼在這裏的一些技巧,我還是個新人,當談到DI /工廠模式/一些,其他模式等:)

非常感謝。

+0

看起來你正試圖建立自己的IoC容器。使用IoC容器時,您不需要工廠。 – 2013-04-10 18:19:47

+1

將依賴注入想象爲*「將依賴關係傳遞給類構造函數」可能會有幫助。*如果您這麼想,那麼所有這些都可能變得更加清晰。對於這個簡單的機制,IoC容器實際上只是很多儀式。因此,如果你的場景與編寫一個以某個接口爲參數的類的想法兼容,然後在構建該類時提供了該接口的一些實現,那麼它對於IoC來說可能是一個很好的候選者。 – 2013-04-10 18:19:59

+0

我不會在這裏添加額外的複雜層。 – 2013-04-10 18:26:15

回答

1

我覺得一般的建議是你應該儘量堅持單一職責原則,而你的情況可以解釋爲使您的控制器相對較小,集中在他們做什麼。這樣,服務依賴關係的數量將會很小,並且通過所有必需的服務不應該是一件麻煩事。

也就是說,有時候可以爲多個服務提供一個單一的接入點,減少傳遞的參數數量,或者允許服務之間的交互(IoC容器不喜歡循環關係/依賴)。

我有必要爲後者,並決定建立,提供給所有服務槽性質的訪問的UnitOfWork類。 UnitOfWork將所有服務作爲構造函數參數,並作爲構造函數參數傳遞給控制器​​。這允許通過IoC構造和注入整個鏈(服務,uow和控制器),並且如果您保持較低的對象構建成本(避免在構造函數中做很多工作),那麼性能開銷將很小。

從實用的角度來看,兩種解決方案都可以。但是,用第二種方法進行代碼化的風險更大,因爲哪裏使用哪種服務尚不清楚。

+0

+1。我絕對同意。 「IServiceFactory」的使用只是聞起來像[Service Locator反模式](http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/),我所有的蜘蛛SOLID-感覺都是叮噹作響這裏。 OP應該可能將這些相關服務組合在一個[聚合服務](http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/)或者[命令模式](http://www.cuttingedge 。它/博客/史蒂芬/樞軸/ entry.php?ID = 91)。 – Steven 2013-04-10 19:20:57

相關問題