2009-07-15 41 views
3

我正在使用結構映射並希望將實例(由容器構造)注入到控制器的屬性中。實例應該被命名並存儲在http會話上下文容器中。 在以前的版本我的申請,我用自定義的DI框架,這是很容易做出這樣的事情:使用具有結構映射的命名會話實例策略的setter insection

public class MyController : Controller 
{ 
    [InjectSession("MySessionInstanceKey")] 
    public MyManager Manager {get; set;} 
} 

有沒有簡單的方式與structuremap辦呢?
或者也許我可以將我的自定義屬性和注入邏輯引入SM框架(以某種方式擴展框架)?
請幫我找到解決這個問題的方法,非常感謝!

P.S.我找到了暫時的解決方法,但它增加了控制器的凝聚力與IoC框架,幷包含了大量的代碼:

private const string ordersBulkManagerKey = "_OrdersBulkManager"; 
public BulkManager OrdersBulkManager 
{ 
    get 
    { 
     var manager = Session[ordersBulkManagerKey] as BulkManager; 
     if(manager == null) 
     Session[ordersBulkManagerKey] = manager 
      = ObjectFactory.GetInstance<BulkManager>(); 
     return manager; 
    } 
} 

所以,我不想使用ObjectFactory.GetInstance那裏...

回答

2

有幾篇關於如何連接配置ASP.NET MVC和StructureMap的博文。 (所以大多數以下代碼是來自各個帖子的摘要。)

實現此目的的常用方法是聲明我們自己的控制器工廠類,這將允許我們通過構造函數注入我們的依賴項。 (ASP.NET MVC使用的默認控制器工廠需要默認的構造函數)

因此,在您的MyController類中,您將擁有一個接受MyManager參數的構造函數(它將由我們自己的參數爲您注入控制器工廠類)

public class MyController : Controller 
{ 
    private readonly ISomeService _someService; 
    //Constructor Injection. 
    public MyController(ISomeService someService){ 
     _someService = someService; 
    } 
} 

下一步將配置ASP.NET MVC做使用這個新的控制器工廠類(我們將其稱爲StructureMapControllerFactory)。

protected void Application_Start() 
{ 

    //This is where you register your concrete types with StructureMap 
    Bootstrapper.ConfigureStructureMap(); 

    //Our very own Controller Factory 
    ControllerBuilder.Current.SetControllerFactory 
    (new StructureMapControllerFactory()); 

    RegisterRoutes(RouteTable.Routes); 
} 

在StructureMapControllerFactory,我們稱之爲ObjectFactory.GetInstance來回報您對我們的控制器(提供我們連線了我們所有的依賴)

public class StructureMapControllerFactory : DefaultControllerFactory 
{ 
    protected override IController GetControllerInstance(Type controllerType) 
    { 
     if (controllerType == null) return null; 
     try 
     { 
      return ObjectFactory.GetInstance(controllerType) as Controller; 
     } 
     catch (StructureMapException) 
     { 
      System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave()); 
      throw; 
     } 
    } 
} 

希望我的解釋是明確的,但讓我知道,如果它不是,我可以擴展它。

順便說一句,下面的代碼片段是關於您的引導程序代碼的樣子的例子。

public static class Bootstrapper 
{ 
    public static void ConfigureStructureMap() 
    { 
     ObjectFactory.Initialize(
     x => x.AddRegistry(new MyApplicationRegistry()));    
    } 
} 

public class MyApplicationRegistry : Registry 
{ 
    public MyApplicationRegistry() 
    { 
     ForRequestedType<ISomeService>() 
     .CacheBy(InstanceScope.Your_Choice_Here) 
     .TheDefault.Is.OfConcreteType<SomeService>(); 
    } 
} 

注意:請參閱StructureMap doc以瞭解各種InstanceScope選項。

+0

感謝的人!構造器注入+生命週期管理=這是我需要的 – IlliakaillI 2010-03-05 14:03:28

2

StructureMap可以控制你的對象的生命週期,所以你不必自己實現

For<IBulkManager>() 
    .LifecycleIs(Lifecycles.GetLifecycle(InstanceScope.HttpSession)) 
    .Use<BulkManager>(); 

所以,你的代碼將變成

public IBulkManager OrdersBulkManager 
{ 
    get { return ObjectFactory.GetInstance<IBulkManager>(); } 
} 
+0

感謝Jon,似乎邏輯的生命週期和範圍部分從我的控制器中消失了,這很好。 對ObjectFactory的引用仍然存在,但我真的不在乎,這是大約8個月前..哈哈 好吧,也許這不是一個好的風格,將DI容器與代碼的其餘部分聯繫起來......但是我的屬性注入的例子是相同的錯誤風格。 所以:我可能應該使用生命週期定義與構造函數注入技術 – IlliakaillI 2010-03-05 13:58:14