4

我需要在使用 IOC Simple Injector 的项目中添加会员重启(RavenDb)

注入实现

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

谢谢你的帮助。

4

2 回答 2

4

Simple Injector 强制您让您的组件拥有一个公共构造函数,因为拥有多个注入构造函数是一种反模式

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

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

container.Register<UserAccountService<HierarchicalUserAccount>>(() =>
    new UserAccountService<HierarchicalUserAccount>(
        container.GetInstance<MembershipRebootConfiguration<HierarchicalUserAccount>>(),
        container.GetInstance<IUserAccountRepository<HierarchicalUserAccount>>()));
于 2014-12-04T12:06:52.893 回答
0

我将在这里介绍如何将 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,我们也必须这样做。因此,我们需要抑制诊断警告,否则会阻止容器验证。

希望所有帮助,如果我的注册有问题,请务必让我知道。

干杯

于 2016-05-01T04:22:39.960 回答