2012-04-10 45 views
3

我正在學習如何使用nInject來開發我正在開發的新應用程序,並且我已經創建了以下示例代碼,可以將其複製/粘貼到簡單的控制檯應用程序中。它成功返回IFoo的一個實例,但我有一個問題。如何使用Ninject在子類中創建實例?

我該如何修改代碼以使FooManager類創建Foo對象的實例而不執行「新建」。內核是否也要注入?但是如果注入了內核並且我將行更改爲var foo = _kernel.Get<IFoo>(),是不是引入了服務定位器反模式?

namespace IOCTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (IKernel kernel = new StandardKernel(new StandardModule())) 
      { 
       // do something with the kernal 
       var mgr = kernel.Get<IFooManager>(); 
       var foo = mgr.GetById(1); 
      } 
     } 
    } 

    public class StandardModule : Ninject.Modules.NinjectModule 
    { 
     public override void Load() 
     { 
      Bind<IDatabase>() 
       .To<Database>() 
       .InTransientScope(); 

      Bind<IFooManager>() 
       .To<FooManager>() 
       .InTransientScope(); 
     } 
    } 

    //****************************************************** 

    public interface IDatabase 
    { 
     object[] GetScalar(int id); 
    } 

    public class Database : IDatabase 
    { 
     public object[] GetScalar(int id) 
     { 
      return new object[] { "RowName" }; 
     } 
    } 

    //****************************************************** 

    public interface IFooManager 
    { 
     IFoo GetById(int id); 
    } 

    public class FooManager : IFooManager 
    { 
     private IDatabase _db; 

     public FooManager(IDatabase db) { _db = db; } 

     public IFoo GetById(int id) 
     { 
      var results = _db.GetScalar(id); 
      var foo = new Foo(); // <-- HOW DO I ELIMINATE THIS DEPENDENCY? 
      foo.Name = results[0].ToString(); 
      return foo; 
     } 
    } 

    //****************************************************** 

    public interface IFoo 
    { 
     string Name { get; set; } 
    } 

    public class Foo : IFoo 
    { 
     public string Name { get; set; } 
    } 

    //****************************************************** 
} 

回答

4

首先你必須考慮Foo的目的。這是某種數據容器還是某種服務?

在第一種情況下,您的代碼完美無瑕。 Datacontainer沒有依賴關係,不應該由IoC容器創建。

在第二種情況下閱讀有關Ninject.Extensions.Factory。

http://www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction/

https://github.com/ninject/ninject.extensions.factory/wiki

+0

謝謝。我也和工廠一起玩過,但最後它似乎是一個圍繞着核心的包裝,並且仍然必須到處通過。由於我使用Foo作爲Datacontainer,因此您的評論讓我感到安慰,在這種情況下使用'新'是可以的! :) – 2012-04-11 13:31:23

2

有幾種方法可以消除這種依賴性。您可以對數據庫依賴關係執行相同的操作,並使用構造函數注入。你可以做財產注入(https://github.com/ninject/ninject/wiki/Injection-Patterns)。另一種方式,也許你正在尋找的是服務地點。要做到這一點,你可以更新你的FooManager ctor來需要一個IKernel。這將自動解決,然後您可以使用傳入的內核來獲取Foo。

public class FooManager : IFooManager 
{ 
    private IDatabase _db; 
    private IKernel _kernel; 

    public FooManager(IDatabase db, IKernel kernel) { _db = db; _kernel = kernel;} 

    public IFoo GetById(int id) 
    { 
     var results = _db.GetScalar(id); 
     // var foo = new Foo(); // <-- HOW DO I ELIMINATE THIS DEPENDENCY? 
     var foo = kernel.Get<IFoo>(); // Like this perhaps 
     foo.Name = results[0].ToString(); 
     return foo; 
    } 
} 
+1

是不是注射籽粒爲服務定位的反模式?但如果你不這樣做,那麼你必須注入一個IFoo的實例。這對我來說真的很奇怪。我現在非常重視這個概念。 – 2012-04-10 15:52:12

+1

@John那麼你可以創建一個工廠,如果你想要建立一個foo對象並作爲IFoo返回。是的服務地點通常被認爲是反模式,但這並不意味着它總是不好,可能是正確的決定。 – 2012-04-10 15:57:10

相關問題