16

我将 C# 与 Microsoft 的 Unity 框架一起使用。我不太确定如何解决这个问题。这可能与我对 Unity 的 DI 缺乏了解有关。

我的问题可以使用以下示例代码来总结:

class Train(Person p) { ... }

class Bus(Person p) { ... }

class Person(string name) { ... }

Person dad = new Person("joe");
Person son = new Person("timmy");

当我在 Bus 上调用 resolve 方法时,如何确定名称为 'timmy' 的 Person 'son' 已被注入,而在解析 Train 时,我如何确定名称为 'joe' 的 Person 'dad' 已解决?

我在想也许使用命名实例?但我不知所措。任何帮助,将不胜感激。

顺便说一句,我宁愿不创建 IPerson 接口。

4

3 回答 3

35

除非您将“joe”和“timmy”分别注册为命名依赖项,否则您无法确定“timmy”是否已注入 Schoolbus。事实上,如果你尝试将同一个类的两个实例注册为未命名的依赖项,你的设置就会模棱两可,根本无法解析Person

一般来说,如果您必须注册很多命名实例,您可能会以错误的方式处理 DI。DI 的主要思想是解决域服务而不是域对象

DI 的主要思想是提供一种机制,允许您将抽象类型(接口或抽象类)解析为具体类型。您的示例没有抽象类型,因此它并没有多大意义。

于 2010-01-06T19:21:09.860 回答
19

解决这个问题的一种方法是使用带有命名注册的注入构造函数。

// Register timmy this way  
Person son = new Person("Timmy");  
container.RegisterInstance<Person>("son", son);  

// OR register timmy this way  
container.RegisterType<Person>("son", new InjectionConstructor("Timmy"));  

// Either way, register bus this way.  
container.RegisterType<Bus>(new InjectionConstructor(container.Resolve<Person>("son")));  

// Repeat for Joe / Train
于 2010-01-06T19:14:29.773 回答
15

马克·西曼做对了。我同情你的困惑。当我学会使用自动依赖注入容器时,我自己经历过。问题是有许多有效和合理的方法来设计和使用对象。然而,只有其中一些方法适用于自动依赖注入容器。

我的个人经历:早在我学会如何使用 Unity 或 Castle Windsor 容器等控制反转容器之前,我就学习了对象构造和控制反转的 OO 原则。我养成了这样写代码的习惯:

public class Foo
{
   IService _service;
   int _accountNumber;

   public Foo(IService service, int accountNumber)
   {
      _service = service;
      _accountNumber = accountNumber;
   }
   public void SaveAccount()
   {
       _service.Save(_accountNumber);

   }
}
public class Program
{
     public static void Main()
     {
        Foo foo = new Foo(new Service(),1234);
        foo.Save();
     }
}

在这个设计中,我的 Foo 类负责将帐户保存到数据库中。它需要一个帐号才能做到这一点,并且需要一个服务来完成这项肮脏的工作。这有点类似于您在上面提供的具体类,其中每个对象在构造函数中都有一些唯一值。当您使用自己的代码实例化对象时,这可以正常工作。您可以在正确的时间传入适当的值。

然而,当我了解自动依赖注入容器时,我发现我不再手动实例化 Foo。容器将为我实例化构造函数参数。这对于像 IService 这样的服务来说是一个极大的便利。但它显然不适用于整数和字符串等。在这些情况下,它将提供一个默认值(如整数为零)。相反,我习惯于传递特定于上下文的值,例如帐号、姓名等……所以我不得不调整我的编码和设计风格,使其如下所示:

public class Foo
{
   IService _service;
   public Foo(IService service)
   {
      _service = service;
   }
   public void SaveAccount(int accountNumber)
   {
       _service.Save(accountNumber);

   }
}
public class Program
{
     public static void Main()
     {
        Foo foo = new Foo(new Service());
        foo.Save(1234);
     }
}

看起来这两个 Foo 类都是有效的设计。但是第二个可用于自动依赖注入,而第一个则不能。

于 2010-09-04T11:41:12.893 回答