gpt4 book ai didi

c# - 向 IoC 注册通用 UnitOfWork<> 时出错

转载 作者:行者123 更新时间:2023-11-30 14:27:30 26 4
gpt4 key购买 nike

我的应用程序中的 DbContext 有一个 UnitOfWork 的通用实现,其工作方式如下:

 public class UnitOfWork<TContext> : IDisposable, IUnitOfWork<TContext>
where TContext : DbContext
{
private readonly TContext _context;

[..UoW default implementations..]

public void Dispose()
{
_context.Dispose();
}
}

和注册...:

public static class SimpleInjectorWebApiInitializer
{
/// <summary>Initialize the container and register it as Web API Dependency Resolver.</summary>
public static void Initialize()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();

InitializeContainer(container);

container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

container.Verify();

GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
}

private static void InitializeContainer(Container container)
{

// For instance:
container.Register(typeof(IUnitOfWork<>), typeof(UnitOfWork<>), Lifestyle.Scoped);
container.RegisterWebApiRequest<IBankRepository, BankRepository>();
container.RegisterWebApiRequest<IBankService, BankService>();

}
}

当我尝试注册此类型和其他服务时,我收到以下警告:

-[生活方式不匹配] UnitOfWork<CustomerContext> (Web API 请求)取决于 CustomerContext( transient )。

-[一次性 transient 组件] CustomerContext 注册为 transient ,但实现了 IDisposable。

我的应用程序架构使用默认的 WebAPI 实现:

[RoutePrefix("customer/banks")]
public class BankController : ApiController
{
private readonly IBankService _bankService;

public BankController(IBankService bankService)
{
_bankService = bankService;
}

[Route]
public IEnumerable<BancoModel> Get()
{
var result = _bankService.GetBanks();
[...mappings and return...]
}
}

我已经尝试抑制这些警告:

Registration registration = container.GetRegistration(typeof(IUnitOfWork<>)).Registration;
registration.SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent, "Dispose called by application code");

..但我收到 InvalidOperationException。

关于如何注册这个有什么想法吗?

最佳答案

您面临的问题是您没有为 CustomerContext 添加注册.

因为 CustomerContext有一个默认的构造函数,Simple Injector 能够为你 Autowiring 这个依赖。但是当 Simple Injector 在第一次调用 GetInstance 时为此进行注册,容器除了使用默认生活方式注册此服务类型外别无选择。然而,Simple Injector 的默认生活方式是:Transient .

换句话说,您收到的诊断警告是正确的,因为 CustomerContext实际上注册为 Transient .

要解决此问题,请为 CustomerContext 添加一个注册作为:

container.Register<CustomerContext>(Lifestyle.Scoped);

您可以删除抑制警告的配置,因为这些“警告”是实际问题!

此时实际上有第三个诊断警告可用。您可以阅读有关 Container-Registered Types 的信息警告 here .此诊断警告通知您对象图中需要的类型不属于您的配置。这是一个信息性警告,因此在验证容器时不会作为异常抛出。信息类别的原因是对于可以是 Transient 的简单类这根本不是问题,并且存在您无法在编译时注册所有类的有效用例。

但是在容器中注册所有需要的类型是一种很好的做法,因为在这种情况下容器完全了解所有类,因此能够尽其所能做到最好 Verify你的配置。

这是良好做法的第二个原因是每个 DI 容器都有不同的“默认生活方式”。简单注入(inject)器默认为 Transient ,而其他人默认为 Singleton .如果您以后要交换 DI 容器,您可能会得到一个在运行时失败的应用程序,因为某些组件突然变成了 Singleton。 .

您收到 InvalidOperationException 的原因抑制警告是由容器(尚未)能够抑制开放通用类型的警告引起的。在这种情况下这是一件好事,因为你必须来寻求帮助!

如果您成功地抑制了这些警告,您很快就会发现自己在调试奇怪的问题。

因为如果您的 DbContext 会发生什么是Transient

每个服务/命令处理程序/查询处理程序/等。依赖于此 DbContext会得到一个不同的!这可能会导致这种情况:

  • 您使用查询处理程序/存储库或任何服务从数据库中获取记录
  • 您将使用另一个服务/命令处理程序中的一些新信息更新实体,该服务/命令处理程序自身依赖于DbContext。 , 因此是一个不同的实例
  • 你调用DbContext.SaveChanges()在可能的另一个类中,同样有它自己的 DbContext 实例,一个 SaveChangesCommandHandlerDecorator例如。因为这个 DbContext没有跟踪数据库未更新的任何更改。

为了完整起见:

警告在 CustomerContext 上给出和 UnitOfWork<CustomerContext> ,因此您应该抑制有关此服务类型注册的警告。幸运的是你没有注册 CustomerContext你必须做更多的工作来抑制 UnitOfwork<CustomerContext 上的警告!

您收到的警告文档是 herehere

关于c# - 向 IoC 注册通用 UnitOfWork<> 时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32658838/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com