如何在 Simple Injector 中使用 Ninject 的命名绑定?
How to use Ninject's Named bindings in Simple Injector?
我有一个使用 Ninject 作为 DI 的 MVC 应用程序,我正计划将其迁移到 Simple Injector。但是我找不到任何替代方法来用 Simple Injector 替换 Ninject 的命名绑定。
绑定:
kernel.Bind<IStudent>().To<Student1>().Named("Senior");
kernel.Bind<IStudent>().To<Student2>().Named("Junior");
kernel.Bind<IStudent>().To<Student3>().Named("Junior");
控制器:
public class StudentController
{
private readonly IEnumerable<IStudent> _seniors;
private readonly IEnumerable<IStudent> _juniors;
public StudentController([named("Senior")] IEnumerable<IStudent> seniors,[named("Junior")] IEnumerable<IStudent> juniors)
{
_seniors=seniors;
_juniors=juniors;
}
}
我提到了几个链接 How to use Ninject's Named bindings in Simple Injector。但是没有任何运气。
有多种选择:
选项 1:使用 [named] 属性
要实现这一点,您将必须重新创建 NamedAttribute
,因为这不存在于简单注入器中,for good reason。
您可以为collection名学生进行以下两种有条件的报名:
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
collection 包装一个 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:通过手动连接 StudentsController。
一个更简单的选择是从 Auto-Wiring 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));
这里我们请求容器创建两个 collection 学生,并为 StudentsController
创建注册,其中两个 collection 都被注入。
请注意,在 Simple Injector 中 collection 是流 。这意味着对 Collection.Create
的调用 不会 创建学生实例,只是对将在迭代时生成学生实例的流的引用。这意味着,可以在应用程序启动时创建流,同时保留注册生活方式。
另请注意,如果您调用 RegisterMvcControllers
,则必须覆盖此控制器的现有注册 class。 This page 展示了如何执行此操作。
选项 4:更改设计。使 'Level' 成为 IStudent 的 属性。控制器内部过滤器。
您可以决定以简化注册的方式更改您的设计。这是否更好在很大程度上取决于上下文,所以请对此持保留态度。但是,当你在表示一个学生是否是学长的IStudent
接口中添加一个Level
属性,或者类似的东西,并根据里面的过滤 管理员,您的注册已减少到以下内容:
container.Collection.Register<IStudent>(typeof(Student1).Assembly);
这里我们使用Auto-Registration搜索所有学生实现并将它们全部注册到一个collection。
在这种情况下,StudentController
将保留一个构造函数参数,但您显然将过滤掉 Composition Root 的责任移到了控制器中。
public class StudentController
{
private readonly IEnumerable<IStudent> _students;
public StudentController(IEnumerable<IStudent> students)
{
_students = students;
}
}
我有一个使用 Ninject 作为 DI 的 MVC 应用程序,我正计划将其迁移到 Simple Injector。但是我找不到任何替代方法来用 Simple Injector 替换 Ninject 的命名绑定。
绑定:
kernel.Bind<IStudent>().To<Student1>().Named("Senior");
kernel.Bind<IStudent>().To<Student2>().Named("Junior");
kernel.Bind<IStudent>().To<Student3>().Named("Junior");
控制器:
public class StudentController
{
private readonly IEnumerable<IStudent> _seniors;
private readonly IEnumerable<IStudent> _juniors;
public StudentController([named("Senior")] IEnumerable<IStudent> seniors,[named("Junior")] IEnumerable<IStudent> juniors)
{
_seniors=seniors;
_juniors=juniors;
}
}
我提到了几个链接 How to use Ninject's Named bindings in Simple Injector。但是没有任何运气。
有多种选择:
选项 1:使用 [named] 属性
要实现这一点,您将必须重新创建 NamedAttribute
,因为这不存在于简单注入器中,for good reason。
您可以为collection名学生进行以下两种有条件的报名:
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
collection 包装一个 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:通过手动连接 StudentsController。
一个更简单的选择是从 Auto-Wiring 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));
这里我们请求容器创建两个 collection 学生,并为 StudentsController
创建注册,其中两个 collection 都被注入。
请注意,在 Simple Injector 中 collection 是流 。这意味着对 Collection.Create
的调用 不会 创建学生实例,只是对将在迭代时生成学生实例的流的引用。这意味着,可以在应用程序启动时创建流,同时保留注册生活方式。
另请注意,如果您调用 RegisterMvcControllers
,则必须覆盖此控制器的现有注册 class。 This page 展示了如何执行此操作。
选项 4:更改设计。使 'Level' 成为 IStudent 的 属性。控制器内部过滤器。
您可以决定以简化注册的方式更改您的设计。这是否更好在很大程度上取决于上下文,所以请对此持保留态度。但是,当你在表示一个学生是否是学长的IStudent
接口中添加一个Level
属性,或者类似的东西,并根据里面的过滤 管理员,您的注册已减少到以下内容:
container.Collection.Register<IStudent>(typeof(Student1).Assembly);
这里我们使用Auto-Registration搜索所有学生实现并将它们全部注册到一个collection。
在这种情况下,StudentController
将保留一个构造函数参数,但您显然将过滤掉 Composition Root 的责任移到了控制器中。
public class StudentController
{
private readonly IEnumerable<IStudent> _students;
public StudentController(IEnumerable<IStudent> students)
{
_students = students;
}
}