我有一个使用Ninject for DI的MVC应用程序,我计划将其迁移到Simple Injector。但是我找不到用Simple Injector替换Ninject命名绑定的替代方法。
结合:
email
控制器:
kernel.Bind<IStudent>().To<Student1>().Named("Senior");
kernel.Bind<IStudent>().To<Student2>().Named("Junior");
kernel.Bind<IStudent>().To<Student3>().Named("Junior");
我提到了几个链接How to use Ninject's Named bindings in Simple Injector。但是没有运气。
答案 0 :(得分:2)
有很多选择:
选项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");
每个条件注册都为Registration
集合包装IStudent
。谓词过滤目标,在本例中为构造函数参数,用于其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:手动连接StudentsController。
更简单的选择是从自动接线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:更改设计。制作&#39;等级&#39; IStudent的财产。在控制器内部过滤。
您可以决定以简化注册的方式更改设计。这是否更好取决于具体情况,所以请带上一粒盐。但是,当您向Level
接口添加IStudent
属性或类似内容时,表示学生是否为高级,并根据 inside 控制器进行过滤,您的注册大大减少到以下几点:
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;
}
}