成员重启使用Simple Injector替换Ninject

时间:2014-12-04 11:32:40

标签: asp.net-web-api ninject ravendb simple-injector membershipreboot

我需要将成员资格重启(RavenDb)添加到使用IOC Simple Injector的项目中

Ninject实施

var config = MembershipRebootConfig.Create();
kernel.Bind<MembershipRebootConfiguration<HierarchicalUserAccount>>().ToConstant(config);
kernel.Bind<UserAccountService<HierarchicalUserAccount>>().ToSelf();   kernel.Bind<AuthenticationService<HierarchicalUserAccount().To<SamAuthenticationService<HierarchicalUserAccount>>();
kernel.Bind<IUserAccountRepository<HierarchicalUserAccount>>().ToMethod(ctx => new BrockAllen.MembershipReboot.RavenDb.RavenUserAccountRepository("RavenDb"));
kernel.Bind<IUserAccountQuery>().ToMethod(ctx => new BrockAllen.MembershipReboot.RavenDb.RavenUserAccountRepository("RavenDb"));

简单的注入器实现

container.Register(MembershipRebootConfig.Create);
container.Register<UserAccountService<HierarchicalUserAccount>>();
container.Register<AuthenticationService<HierarchicalUserAccount>, SamAuthenticationService<HierarchicalUserAccount>>();
container.Register<IUserAccountRepository<HierarchicalUserAccount>>(() => new RavenUserAccountRepository("RavenDb"), Lifestyle.Singleton);
container.Register<IUserAccountQuery>(() => new RavenUserAccountRepository("RavenDb"));

在行

container.Register<UserAccountService<HierarchicalUserAccount>>();

我有错误 要使容器能够创建UserAccountService,它应该只包含一个公共构造函数,但它有2个。 参数名称:TConcrete

感谢您的帮助。

2 个答案:

答案 0 :(得分:4)

Simple Injector强制您让组件拥有一个公共构造函数,因为multiple injection constructors is an anti-pattern

如果UserAccountService是您的代码库的一部分,您应该删除不应用于自动连接的构造函数。

如果UserAccountService是可重用库的一部分,那么在这种情况下应该阻止使用容器的自动连接功能,如here所述。在这种情况下,您应该回退自己连接类型并让代码调用正确的构造函数,例如:

container.Register<UserAccountService<HierarchicalUserAccount>>(() =>
    new UserAccountService<HierarchicalUserAccount>(
        container.GetInstance<MembershipRebootConfiguration<HierarchicalUserAccount>>(),
        container.GetInstance<IUserAccountRepository<HierarchicalUserAccount>>()));

答案 1 :(得分:0)

我将在此处包含如何将Ninject配置转换为SimpleRejector,以用于MembershipReboot存储库(我克隆的)中的单租户示例。我认为这对于那些正在寻找如何解决这个问题的人来说可能是有益的,因为它可能会节省一些时间。

首先,Single Tenant样本的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,例如注册用户。它不会使用更大的每个请求绑定的tansactions。因此,稍后在同一请求中使用相同的DefaultMembershipRebootDatabase上下文不会导致任何奇怪的MR问题。

然而,如果您想在创建MR UserAccount的同一操作期间创建域用户,则需要考虑一些事情。 (域用户可能包含除密码之外的更多信息,如名字和姓氏,DOB等)。将MR UserAccount绑定到域用户(具有诸如名称,地址等附加用户信息)是常见用例。那么,如果在创建MR UserAccount成功后创建域用户失败,会发生什么?我不知道。也许作为回滚的一部分,您删除MR用户。但是注册邮件已经发送了。所以,这些是你在这里面临的问题。

如您所见,在Simple Tenant示例中,Brock将IUserAccountRepository和IUserAccountQuery都注册到DefaultUserAccountRepository。这显然是设计的,所以如果我们想要使用MR的UserAccountService和AuthenticationService,我们也必须这样做。因此,我们需要禁止诊断警告,否则会阻止Container进行验证。

希望所有帮助都能让我知道我的注册是否有问题。

干杯