2011-06-10 84 views
2

我在我的代碼中有som工廠類,不喜歡對Structermap的調用。我該如何正確地做到這一點?StructureMap和工廠類

class ManagerBaseFactory 
{ 
    public ManagerBase GetInstance(SomeEnum e) 
    { 
     Type t; 

     switch (e) 
     { 
      case SomeEnum.A: 
       t = typeof(Manager1); 
      case SomeEnum.B: 
       t = typeof(Manager2); 
      case SomeEnum.C: 
       t = typeof(Manager3); 
     } 
     return (ManagerBase)StructureMap.ObjectFactory.GetInstance(t); 
    } 
} 

回答

2

我沒有看到這種方式使用結構圖的問題。目前的解決方案你不喜歡什麼?

您可以使用命名實例,您甚至不再需要該工廠。 structuremap link

​​

你可以比只調用

SomeEnum e = SomeEnum.A; 
ObjectFactory.GetNamedInstance<ManagerBase>(e.ToString()); 
+0

ManagerBaseFactory不可測試。我希望在Main中只有一個對Structermap的調用。 – Hans 2011-06-11 20:31:04

+0

我不確定我是否支持這種配置。處理器看起來像什麼? – Hans 2011-06-11 20:32:02

+0

這只是我從結構手冊拿來的一個例子,處理器並不重要。這個東西是你可以使用結構圖來獲取一個對象的特定實例(在你的汽車ManagerBase中)的一個名字,你的情況可以是枚舉值。我更新了這個例子,讓它符合我的想法。 – llMll 2011-06-12 14:43:36

0

目前尚不清楚你反對什麼部分獲取正確的一個。您可以進行的一項改進是讓ManagerBaseFactory在其構造函數中採用​​,您可以使用它代替ObjectFactory靜態網關。然後,您可以將ManagerBaseFactory拉出容器,容器將自己注入工廠。工廠將更容易進行單元測試,而無需靜態依賴。

你也可以把return語句直接在交換機這樣你就可以採取仿製藥的優勢:

case SomeEnum.A: 
    return _container.GetInstance<Manager1>(); 
+0

ManagerBaseFactory不可測試,因爲它使用DI容器。 – Hans 2011-06-11 20:35:13

+0

它絕對是可測試的。這就是爲什麼我建議採用IContainer而不是使用ObjectFactory。在你的測試中,創建一個新的Container實例,用你正在測試的場景所需的最少量加載它,並將它傳遞給ManagerBaseFactory。或者只是將IContainer存根。 – 2011-06-24 13:44:35

2

如果你絕對不希望自己的ManagerBaseFactory使用的容器,你可以給它訪問所有來自容器的ManagerBase實現,並讓它返回正確的。當StructureMap在構造函數中看到一個IEnumerable類型時,它將注入它知道的那個類型的所有實例。

class ManagerBaseFactory 
{ 
    private readonly IEnumerable<ManagerBase> _managers; 

    public ManagerBaseFactory(IEnumerable<ManagerBase> managers) 
    { 
     _managers = managers; 
    } 

    public ManagerBase GetInstance(SomeEnum e) 
    { 
     Type t; 

     switch (e) 
     { 
      case SomeEnum.A: 
       t = typeof(Manager1); 
       break; 
      case SomeEnum.B: 
       t = typeof(Manager2); 
       break; 
      case SomeEnum.C: 
       t = typeof(Manager3); 
       break; 
      default: 
       return null; 
     } 
     return _managers.FirstOrDefault(m => m.GetType().Equals(t)); 
    } 
} 

當然,你需要確保所有的ManagerBase實現在容器中裝入:

var container = new Container(x => 
{ 
    x.Scan(scan => 
    { 
     scan.TheCallingAssembly(); 
     scan.AddAllTypesOf<ManagerBase>(); 
    }); 
});