2012-07-25 108 views
2

我有一個asp.net-mvc網站,我正在使用LinFu做IOC。我遇到了一些問題,其中一些操作具有我要注入到控制器中的依賴項,但是如果我調用依賴於該操作的操作,我只想初始化依賴項。有沒有更好的方法來做asp.net-mvc中的IOC?

所以在我的控制器我有我的控制器驗證碼:

public PersonController 
    { 

    private IPeopleImporter _peopleImporter; 

    public override void Initialize(LinFu.IoC.Interfaces.IServiceContainer source) 
    { 
     _peopleImporter= source.GetService<IPeopleImporter>(); 
     base.Initialize(source); 
    } 

    public JsonResult GetDetails(int id) 
    { 
     var p = _peopleImporter.Get(id); 
     var personDetails = new {p.Id, p.FirstName, p.LastName, StandardId = p.StandardIdLogin, p.PersonNumber}; 
     return Json(personDetails); 
    } 
    } 

到initiatize PeopleImporter是相當昂貴的,所以我的問題是,我要解決兩兩件事:

  1. 我想使IPeopleImporter的implementatioo「可插拔」這樣我就可以在國際奧委會的界面到控制器

  2. 我有很多的動作,所以我不希望如果用戶從不調用需要它的特定操作,則開始IPeopleImporter的開銷。這似乎是在上面的代碼,我這樣做,initiatization上PersonController的每一個電話

我initiatization代碼是這樣的:

this.AddService(typeof(IPeopleImporter), typeof(DatabaseImporter), LifecycleType.Singleton); 

這似乎是常見的模式/問題。有沒有推薦的解決方案。在此期間,替代方案(以避免性能打擊是簡單的「新」的內置控制器內置(並避免國際奧委會)?

+0

我不知道LinFu,但許多其他IOC框架提供工廠注入,可用於在需要時實例化實例。 – Eranga 2012-07-25 03:47:42

+0

你所顯示的不是IoC。你一定在這裏混淆了這些條款。在IoC中,控制器將依賴關係作爲構造函數參數。在你的例子中,你將你的控制器綁定到DI框架(你的情況下是LinFu),並且你正在使用Service Locator模式(在Initialize方法中,你正在查詢你的DI框架來檢索依賴關係)。這被認爲是反模式。 IoC中的 – 2012-07-27 13:08:04

回答

1

您可以對任務使用下一個技巧。 你可以注入這種類型的不IPeopleImporter的實例,但工廠:

private readonly Func<IPeopleImporter> _peopleImporterFactory; 

,並使用該工廠在你的行動,你需要它:

var peopleImporter = __peopleImporterFactory(); 

例如:

public PersonController 

{

private readonly Func<IPeopleImporter> _peopleImporterFactory; 

public PersonController(Func<IPeopleImporter> peopleImporterFactory) 
{ 
    _peopleImporterFactory = peopleImporterFactory; 
} 

public JsonResult GetDetails(int id) 
{ 
    var peopleImporter = _peopleImporterFactory(); 
    var p = peopleImporter.Get(id); 
    var personDetails = new {p.Id, p.FirstName, p.LastName, StandardId = p.StandardIdLogin, p.PersonNumber}; 
    return Json(personDetails); 
} 

}

0

我通常通過注入依賴項作爲參數來解決這個問題。常見的或低廉的依賴性可以在類的級別被注入而不同尋常的或昂貴的進來作爲參數

下面是企業庫統一一些示例代碼,但你能適應它。

public class UnityActionInvoker : ControllerActionInvoker 
{ 
    readonly IUnityContainer container; 

    public UnityActionInvoker(IUnityContainer container) 
    { 
     this.container = container; 
    } 

    protected override object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) 
    { 
     Type parameterType = parameterDescriptor.ParameterType; 

     if (parameterType != typeof(string) && !parameterType.IsValueType && container.IsRegistered(parameterType)) 
     { 
      return container.Resolve(parameterType).AssertNotNull(); 
     } 

     return base.GetParameterValue(controllerContext, parameterDescriptor); 
    } 
} 

你可以通過這個鉤住這個ControllerActionInvoker在控制器的構造函數中(或在所有控制器的公共基類中)設置Controller.ActionInvoker

這裏是你的控制器可能看起來怎麼樣:

public PersonController 
    { 
    public JsonResult GetDetails(int id, IPeopleImporter _peopleImporter /*injected*/) 
    { 
     ... 
    } 
    } 
3

第一步是到把這個行動統一到一個單獨的控制器。這樣您就不必爲此控制器中的其他操作支付初始化價格。

然後使用真正的IoC模式,而不是您正在使用的服務定位器,它被視爲反模式。在IoC中,控制器不應該知道正在使用的特定DI框架。在IoC中,控制器接收所有依賴關係作爲構造函數參數

public PersonsController: Controller 
{ 
    private readonly IPeopleImporter _peopleImporter; 
    public PersonsController(IPeopleImporter peopleImporter) 
    { 
     _peopleImporter = peopleImporter; 
    } 

    public ActionResult GetDetails(int id) 
    { 
     var p = _peopleImporter.Get(id); 
     var personDetails = new { p.Id, p.FirstName, p.LastName, StandardId = p.StandardIdLogin, p.PersonNumber }; 
     return Json(personDetails, JsonRequestBehavior.AllowGet); 
    } 
} 
+0

可以通過構造函數以外的其他方法注入依賴項。當然,構造函數是最常見的,但不是唯一可能的機制 – 2012-07-30 07:43:00

+0

@RuneFS,是的,沒錯。您可以將屬性注入用於非必需的依賴項。 – 2012-07-30 07:59:43

+0

@Darin - 我同意你的觀點。 。希望從林福遷出,因爲它似乎並不支持適當的國際奧委會,在那裏控制員不需要參考國際奧委會容器。 – leora 2012-07-30 16:47:51

相關問題