我正在做一些工作,但我认为它可能会做得更好(因此,具有更多的可维护性)。

我正在使用Ninject将各种东西注入到控制器中。我需要解决的问题是每个存储库的DbContext需要相同。即内存中的同一个对象。

虽然,下面的代码确实实现了这一点,我的Ninject 通用配置文件 已经开始变得相当混乱,因为我必须为每个控制器编写类似的代码:

kernel.Bind<OrderController>().ToMethod(ctx =>
{
    var sharedContext = ctx.Kernel.Get<TTSWebinarsContext>();
    var userAccountService = kernel.Get<UserAccountService>();
    ILogger logger = new Log4NetLogger(typeof(Nml.OrderController));
    ILogger loggerForOrderManagementService = new Log4NetLogger(typeof(OrderManagementService));


    var orderManagementService = new OrderManagementService(
        new AffiliateRepository(sharedContext),
        new RegTypeRepository(sharedContext),
        new OrderRepository(sharedContext),
        new RefDataRepository(),
        new WebUserRepository(sharedContext),
        new WebinarRepository(sharedContext),
        loggerForOrderManagementService,
        ttsConfig
        );

    var membershipService = new MembershipService(
        new InstitutionRepository(sharedContext),
        new RefDataRepository(),
        new SamAuthenticationService(userAccountService),
        userAccountService,
        new WebUserRepository(sharedContext)
        );

    return new OrderController(membershipService, orderManagementService, kernel.Get<IStateService>(), logger);
}).InRequestScope();    

有没有更整洁的方法来做到这一点?

编辑

尝试了以下代码。一旦我发出第二个请求,就会出现一个异常,即DbContext已经被释放。

kernel.Bind<TTSWebinarsContext>().ToSelf().InRequestScope();

string baseUrl = HttpRuntime.AppDomainAppPath;
kernel.Bind<IStateService>().To<StateService>().InRequestScope();
kernel.Bind<IRefDataRepository>().To<RefDataRepository>().InRequestScope().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>()); 

var config = MembershipRebootConfig.Create(baseUrl, kernel.Get<IStateService>(), kernel.Get<IRefDataRepository>());
var ttsConfig = TtsConfig.Create(baseUrl);

kernel.Bind<MembershipRebootConfiguration>().ToConstant(config);
kernel.Bind<TtsConfiguration>().ToConstant(ttsConfig);

kernel.Bind<IAffiliateRepository>().To<AffiliateRepository>().InRequestScope().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());
kernel.Bind<IWebinarRepository>().To<WebinarRepository>().InRequestScope().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());
kernel.Bind<IWebUserRepository>().To<WebUserRepository>().InRequestScope().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());
kernel.Bind<IOrderRepository>().To<OrderRepository>().InRequestScope().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());
kernel.Bind<IInstitutionRepository>().To<InstitutionRepository>().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());
kernel.Bind<IUserAccountRepository>().To<DefaultUserAccountRepository>().InRequestScope();
kernel.Bind<IRegTypeRepository>().To<RegTypeRepository>().InRequestScope().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());

kernel.Bind<UserAccountService>().ToMethod(ctx =>
{
    var userAccountService = new UserAccountService(config, ctx.Kernel.Get<IUserAccountRepository>());
    return userAccountService;
});

kernel.Bind<IOrderManagementService>().To<OrderManagementService>().InRequestScope();

//RegisterControllers(kernel, ttsConfig);

kernel.Bind<AuthenticationService>().To<SamAuthenticationService>().InRequestScope();
kernel.Bind<IMembershipService>().To<MembershipService>().InRequestScope();

我误解了InRequestScope。

有帮助吗?

解决方案

编辑:.InRequestScope() 将确保所有被注入的东西 那个 绑定将在注入(创建)期间接收完全相同的实例 HttpContext.Current 是一样的。这意味着当客户端发出请求并且内核被要求为实例提供 .InRequestScope(), ,它将为完全相同的请求返回相同的实例。现在,当客户端发出另一个请求时,将创建另一个唯一实例。当请求结束时,ninject将处理实例,以防它实现 IDisposable.

然而 考虑以下场景:

public class A
{
  private readonly DbContext dbContext;

  public A(DbContext dbContext)
  {
      this.dbContext = dbContext;
  }
 }

和装订:

IBindingRoot.Bind<DbContext>().ToSelf().InRequestScope();
IBindingRoot.Bind<A>().ToSelf().InSingletonScope();

你给自己带来了一个大问题。有两种情况可以解决这个问题:

  1. 您正在尝试创建一个 A 请求之外。它会失败。实例化 DbContext, ,ninject会寻找HttpContext。当前-这是空的时间-并抛出异常。
  2. 您正在尝试创建一个 A 在请求期间。实例化将成功。但是,当您尝试使用 A (正在访问 DbContext 反过来)在请求之后或在新请求期间,它会抛出一个 ObjectDisposedException

总结一下,一个 ObjectDisposedException 当您访问 DbContext 可以 只有 由两种情况引起:-你正在处理 DbContext (或一些组件,反过来处置 DbContext)在请求结束之前。-你正在参考 DbContext (再次,或指向某些组件,该组件又引用 DbContext)跨越请求边界。

就这样。没有什么复杂的,但你的对象图。

所以什么会帮助绘制一个对象图。从根/请求根开始。然后当你完成后,从 DbContext 看看是谁打来的 Dispose() 在上面。如果您的代码中没有使用,则必须是Ninject在请求结束时进行清理。这意味着,您需要检查所有对 DbContext.有人在请求之间保留引用。

原答案:你应该看看范围: https://github.com/ninject/ninject/wiki/Object-Scopes 具体来说, .InRequestScope() -或者在不适用于您的问题的情况下 - .InCallScope() 你应该很感兴趣。

正如你已经在使用 .InRequestScope() 对于原始绑定,我建议绑定共享上下文类型也 .InRequestScope() 应该是足够的。这意味着每一个依赖 OrderController 将接收相同的网络研讨会上下文实例。此外,如果同一请求中的其他人想要注入网络研讨会上下文,他也将获得相同的实例。

你应该看看范围: https://github.com/ninject/ninject/wiki/Object-Scopes 具体来说, .InRequestScope() -或者在不适用于您的问题的情况下 - .InCallScope() 你应该很感兴趣。

正如你已经在使用 .InRequestScope() 对于原始绑定,我建议绑定共享上下文类型也 .InRequestScope() 应该是足够的。这意味着每一个依赖 OrderController 将接收相同的网络研讨会上下文实例。此外,如果同一请求中的其他人想要注入网络研讨会上下文,他也将获得相同的实例。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top