[英]Is property injection considered to be bad?
演示問題的示例解決方案:
class World
{
public override string ToString()
{
return "Hello World";
}
}
class Hello
{
[Inject]
public World theWorld { get; set; }
public Hello(IKernel kernel)
{
kernel.Inject(this);
}
public override string ToString()
{
return theWorld.ToString();
}
}
class Program
{
static IKernel kernel = new StandardKernel();
static void RegisterServices()
{
kernel.Bind<World>().ToSelf();
}
static void Main(string[] args)
{
RegisterServices();
Hello hello = new Hello(kernel);
Console.WriteLine(hello.ToString());
Console.ReadLine();
}
}
這就是我讓屬性注入實際工作的方式。
如果出現以下情況,它將不起作用:
kernel.Inject(this);
.對我來說,這樣做只是為了獲得一個屬性的實例似乎是非常多余和錯誤的。 有沒有更簡單的方法,或者我還沒有考慮過什么?
構造函數注入通常是比屬性注入更有利的技術,因為屬性注入會導致 時間耦合代碼異味。 因此,屬性注入應該僅用於真正可選的依賴項(這不是您的情況)。 然而,依賴性幾乎不應該是可選的。 即使沒有依賴項的實現,與注入null
引用相比,創建和注入空對象實現通常更好。 與其使用屬性注入,不如通過構造函數注入所有必需的依賴項。
另一個導致相當大缺點的做法是,當您讓應用程序代碼依賴於 DI 容器本身(或表示容器的解析 API 的抽象)時。 這是一種稱為Service Locator的反模式。 您應該引用容器的唯一位置是在您的Composition Root 內。 您示例中的Program
類代表 Composition Root。
相反,您的Hello
類應該簡單地接受World
作為必需的構造函數參數:
class Hello
{
private readonly World theWorld;
public Hello(World world)
{
this.theWorld = world ?? throw new ArgumentNullException("world");
}
public override string ToString()
{
return this.theWorld.ToString();
}
}
請注意如何從此類中完全刪除對容器的任何引用。 這使得類更簡單、更易於維護、更易於測試,甚至可以在不使用 DI 容器的情況下組合此類; 一種通常稱為Pure DI的做法。 當您的應用程序很小時,Pure DI 甚至可以是比使用容器更好的選擇。
以下是您的Program
類在使用 Ninject 時的樣子:
class Program
{
static void Main(string[] args)
{
// Configure
var kernel = new StandardKernel();
kernel.Bind<Hello>().ToSelf();
kernel.Bind<World>().ToSelf();
// Resolve
var hello = kernel.Get<Hello>();
// Use
Console.WriteLine(hello.ToString());
Console.ReadLine();
}
}
如果沒有容器,它將如下所示:
class Program
{
static void Main(string[] args)
{
// Resolve
var hello = new Hello(new World());
// Use
Console.WriteLine(hello.ToString());
Console.ReadLine();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.