如何在Simple Injector中使用Ninject的命名绑定?

时间:2018-06-14 06:58:10

标签: c# dependency-injection ninject simple-injector ninject.web.mvc

我有一个使用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。但是没有运气。

1 个答案:

答案 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;
    }
}