2010-10-15 96 views
3

在配置StructureMap容器​​時是否可以將請求類型作爲參數傳遞。StructureMap獲取請求類型

例如:

  container.Configure(x => { 
       x.For<ILogger>().Use(new TestLogger(log.Add, requestingType));   
      }); 

人請求類型爲消費對象的類型:

public class SomeClass 
{ 
    private readonly ILogger logger; 
    public SomeClass(ILogger logger) 
    { 
     this.logger = logger; 
    } 
} 

所以傳遞到記錄器的類型將是SomeNamespace.SomeClass。

感謝, 本

回答

3

您可以輕鬆地通過使用StructureMap的IContext訪問請求的類型。

ObjectFactory.Configure(
    x => { 
     x.For<ILogger>().Use(context => new TestLogger(context.ParentType)); 
    }); 

在上述語句中,context.ParentType返回由StructureMap創建的類型。

傑里米米勒在博客文章中也介紹了這個話題。本文使用過時的語法,但它仍然是相關的:http://codebetter.com/jeremymiller/2009/01/15/using-the-build-session-in-structuremap/

如果您想檢查所有在IContext可用的屬性,你可以使用匿名函數,並設置一個斷點在回行,像這樣:

ObjectFactory.Configure(
    x => { 
     x.For<ILogger>() 
       .Use(context => 
       { 
        // Set breakpoint here and inspect the context 
        return new TestLogger(context.ParentType); 
       }); 
    }); 

更新:

確保使用.AlwaysUnique()(這相當於.CacheBy的較舊的語法(InstanceScope.Unique)),否則將StructureMap緩存ILogger的第一次請求這將導致原來的記錄器bein g在單個GetInstance()調用期間被注入到ILogger的所有後續請求中。

如果已經嵌套在每個需要ILogger所以對於ObjectFactory.GetInstance < ISomeClass>(一個請求類)這可以容易地發生將導致ILogger被用於在層次結構中的最深的類創建,然後所有其他類將收到相同的ILogger實例,這很可能是你要做的不是想要發生。

因此,採取這種更新和Ben的小費考慮,這裏有一個更好的解決方案:

x.For<ILogger>() 
    .AlwaysUnique() 
    .Use(c => new TestLogger(c.ParentType ?? c.BuildStack.Current.ConcreteType)); 
+1

謝謝,解決了這一段時間後,但忘了我曾問過。我發現'ctx.ParentType'有時返回null,所以做到以下幾點:'對於()。使用(ctx => new TestLogger(ctx.ParentType ?? ctx.BuildStack.Current.ConcreteType));' – 2012-07-24 09:43:41

+0

@BenFoster謝謝爲小費。經過測試,我確實看到了這種情況。另外,我注意到StructureMap沒有爲ObjectFactory.GetInstance()的一次調用的層次結構中需要的每個ILogger獲取一個新的ILogger,所以在查看了一下後,我發現使用.AlwaysUnique()方法可以刪除所有的緩存行爲並給出期望的結果。我已經更新了我的答案,以反映我的發現和提示。謝謝。 – 2012-07-24 18:25:09

0

我找到了解決辦法here

基本上我們改變了ILogger接口ILogger<T>並利用在StructureMap泛型類型推理功能。

嚴格地說,這並不回答我是否可以得到請求類型的問題,所以如果你知道如何做到這一點,請回復 - 這將是有益的知道。

0

首先,我想指出一個潛在的問題,使用Use(new Type())註冊一個實例會導致該實例被註冊爲一個單例。爲了避免這種情況,你可以使用(()=> new Type())。

這裏是你如何在配置時獲得請求的類型:

container.Configure(x => { 
    x.For<ILogger>().Use(c => new TestLogger(log.Add, c.Root.RequestedType)); 
}); 
+0

這將返回該實例的類型創建的,不是那種請求實例。例如,從MVC控制器請求一個ILogger,應該傳遞控制器的類型。希望澄清。 – 2010-10-15 21:59:08

+0

啊我明白了,這樣做更有意義。我不知道在StructureMap中做這件事的方法。 – 2010-10-18 15:53:19

+0

解決方案不再有效; IContext.Root不存在於StructureMap 3.0 – Anthony 2014-07-10 11:57:50