演示问题的示例解决方案:
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);
。对我而言,这样做似乎非常过分和错误,只是为了获取属性的实例。是否有更简单的方法或我没有考虑过什么?
答案 0 :(得分:8)
属性注入通常很糟糕,因为它会导致Temporal Coupling。属性注入应仅用于真正可选的依赖项(在您的情况下不是这样)。然而,依赖性几乎不应该是可选的。即使在没有依赖项实现的情况下,注入Null Object实现也比注入空引用更好。应通过构造函数注入所有必需的依赖项。
另一个不好的做法是让您的应用程序代码依赖于容器本身。这是一种称为Service Locator的反模式。您应该引用容器的唯一位置是Composition Root,即您所在的Program
类。
相反,您的Hello
类应该只接受World
作为必需的构造函数参数:
class Hello
{
private readonly World theWorld;
public Hello(World theWorld) {
if (theWorld == null) throw new ArgumentNullException("theWorld");
this.theWorld = theWorld;
}
public override string ToString() {
return theWorld.ToString();
}
}
请注意我们如何从此类中完全删除对容器的任何引用。这使得类更简单,更易于维护,更易于测试,并且可以在不使用DI容器工具的情况下组成该类;通常称为Pure DI的做法。当您的应用程序很小时,Pure DI可能是比使用容器更好的选择。
以下是您的Program
课程的样子:
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();
}
}