有很多选择:
选项 1:使用 [named] 属性
要实现这一点,您必须重新创建 NamedAttribute,因为这不是 Simple Injector 中存在的东西,for good reason。
您可以对学生集合进行以下两种条件注册:
container.RegisterConditional<IEnumerable<IStudent>>(
container.Collection.CreateRegistration<IStudent>(
typeof(Student1)),
c => c.Consumer.Target.GetCustomAttribute<namedAttribute>()?.Name == "Senior");
container.RegisterConditional<IEnumerable<IStudent>>(
container.Collection.CreateRegistration<IStudent>(
typeof(Student2),
typeof(Student3)),
c => c.Consumer.Target.GetCustomAttribute<namedAttribute>()?.Name == "Junior");
每个条件注册都为IStudent 集合包装一个Registration。谓词过滤目标,在本例中为构造函数参数,以获取其 namedAttribute 的名称。
选项 2:没有命名属性,通过检查参数名称
然而,一个更简单的选择是完全放弃命名属性,只根据构造函数参数的名称进行过滤:
container.RegisterConditional<IEnumerable<IStudent>>(
container.Collection.CreateRegistration<IStudent>(
typeof(Student1)),
c => c.Consumer.Target.Name == "seniors");
container.RegisterConditional<IEnumerable<IStudent>>(
container.Collection.CreateRegistration<IStudent>(
typeof(Student2),
typeof(Student3)),
c => c.Consumer.Target.Name == "juniors");
这种注册方式与选项 1 几乎相同,但现在我们根据参数的实际名称进行过滤,而不是根据其属性。
选项 3:手动连接 StudentController。
一个更简单的选择是从自动接线StudentsController 恢复为手动接线,如下所示:
var seniors = container.Collection.Create<IStudent>(typeof(Student1));
var juniors = container.Collection.Create<IStudent>(typeof(Student2), typeof(Student3));
container.Register(() => new StudentController(seniors: seniors, juniors: juniors));
这里我们请求Container创建两个学生集合,并为StudentsController创建注册,两个集合都被注入其中。
请注意,在 Simple Injector 集合是流。这意味着对Collection.Create 的调用确实不创建学生实例,只是对迭代时将产生学生实例的流的引用。这意味着,可以在应用程序启动时创建流,同时保留注册的生活方式。
另外请注意,如果您调用RegisterMvcControllers,您将不得不覆盖此控制器类的现有注册。 This page 展示了如何做到这一点。
选项 4:更改设计。使“级别”成为 IStudent 的属性。在控制器内部过滤。
您可以决定以简化注册的方式更改您的设计。这是否更好在很大程度上取决于上下文,所以请持保留态度。但是,当您将 Level 属性或类似属性添加到表示学生是否为大四学生的 IStudent 接口,并基于控制器内部进行过滤时,您的注册非常大大简化为以下内容:
container.Collection.Register<IStudent>(typeof(Student1).Assembly);
在这里,我们使用自动注册来搜索所有学生实现并将它们全部注册到一个集合中。
在这种情况下,StudentController 将保留一个构造函数参数,但您显然将过滤责任从Composition Root 移到了控制器中。
public class StudentController
{
private readonly IEnumerable<IStudent> _students;
public StudentController(IEnumerable<IStudent> students)
{
_students = students;
}
}