我将在这里介绍如何将 MembershipReboot 存储库(我克隆的)中的单租户示例的 Ninject 配置转换为 Simple Injector。我认为这可能对任何正在寻找解决方法的人有益,因为它可以节省他们一些时间。
首先,单租户示例的 NinjectWebCommon 类中的配置为:
var config = MembershipRebootConfig.Create();
kernel.Bind<MembershipRebootConfiguration>().ToConstant(config);
kernel.Bind<DefaultMembershipRebootDatabase>().ToSelf();
kernel.Bind<UserAccountService>().ToSelf();
kernel.Bind<AuthenticationService>().To<SamAuthenticationService>();
kernel.Bind<IUserAccountQuery>().To<DefaultUserAccountRepository>().InRequestScope();
kernel.Bind<IUserAccountRepository>().To<DefaultUserAccountRepository>().InRequestScope();
现在,我将列出整个 SimpleInjectorInitializer 类,该类从通过 SimpleInjector.MVC3 Nuget 包添加到项目中的类开始,并跟进注释:
public static class SimpleInjectorInitializer
{
/// <summary>Initialize the container and register it as MVC3 Dependency Resolver.</summary>
public static void Initialize()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
InitializeContainer(container);
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
private static void InitializeContainer(Container container)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<DefaultMembershipRebootDatabase, BrockAllen.MembershipReboot.Ef.Migrations.Configuration>());
var config = MembershipRebootConfig.Create();
container.Register(() => config, Lifestyle.Singleton);
container.Register(() => new DefaultMembershipRebootDatabase(), Lifestyle.Scoped);
container.Register<IUserAccountQuery, DefaultUserAccountRepository>(Lifestyle.Scoped); // per request scope. See DefaultScopedLifestyle setting of container above.
container.Register<IUserAccountRepository, DefaultUserAccountRepository>(Lifestyle.Scoped);
container.Register(() => new UserAccountService(container.GetInstance<MembershipRebootConfiguration>(), container.GetInstance<IUserAccountRepository>()));
container.Register<AuthenticationService, SamAuthenticationService>();
var iUserAccountQueryRegistration = container.GetRegistration(typeof(IUserAccountQuery)).Registration;
var iUserAccountRepositoryRegistration = container.GetRegistration(typeof(IUserAccountRepository)).Registration;
iUserAccountQueryRegistration.SuppressDiagnosticWarning(DiagnosticType.TornLifestyle, "Intend for separate Objects");
iUserAccountRepositoryRegistration.SuppressDiagnosticWarning(DiagnosticType.TornLifestyle, "Intend for separate Objects");
}
}
使用工厂函数将配置范围限定为 Singleton 与 Ninject 的 ToConstant 几乎相同。DefaultMembershipRebootDatabase 是明显的偏离,但老实说,我认为 MR 的 DefaultMembershipRebootDatabase 的范围是瞬态还是每个 Web 请求都无关紧要。每次执行操作(例如注册用户)时,它都会调用 SaveChanges。它不使用更大的、每个请求绑定的事务。因此,稍后在同一请求中使用相同的 DefaultMembershipRebootDatabase 上下文不会导致任何奇怪的 MR 问题。
但是,如果您想在创建 MR UserAccount 的同一操作期间创建域用户,则需要考虑会发生什么。(域用户可能包含密码以外的更多信息,例如名字和姓氏、出生日期等)。将 MR UserAccount 绑定到域用户(带有额外的用户信息,例如姓名、地址等)是一个常见的用例。那么如果在创建MR UserAccount成功后创建Domain User失败了怎么办?我不知道。也许作为回滚的一部分,您删除了 MR 用户。但是注册邮件已经发送了。因此,这些是您在这里面临的问题。
如您所见,在 Simple Tenant 示例中,Brock 将 IUserAccountRepository 和 IUserAccountQuery 都注册到 DefaultUserAccountRepository。这显然是设计使然,所以如果我们想使用 MR 的 UserAccountService 和 AuthenticationService,我们也必须这样做。因此,我们需要抑制诊断警告,否则会阻止容器验证。
希望所有帮助,如果我的注册有问题,请务必让我知道。
干杯