C# 注册通用工作单元时出错<&燃气轮机;与国际奥委会
在我的应用程序中,我的DbContext有一个UnitOfWork的通用实现,其工作原理如下:C# 注册通用工作单元时出错<&燃气轮机;与国际奥委会,c#,asp.net-web-api,inversion-of-control,ioc-container,simple-injector,C#,Asp.net Web Api,Inversion Of Control,Ioc Container,Simple Injector,在我的应用程序中,我的DbContext有一个UnitOfWork的通用实现,其工作原理如下: public class UnitOfWork<TContext> : IDisposable, IUnitOfWork<TContext> where TContext : DbContext { private readonly TContext _context; [..UoW default implementations..]
public class UnitOfWork<TContext> : IDisposable, IUnitOfWork<TContext>
where TContext : DbContext
{
private readonly TContext _context;
[..UoW default implementations..]
public void Dispose()
{
_context.Dispose();
}
}
公共类UnitOfWork:IDisposable,IUnitOfWork
其中TContext:DbContext
{
私有只读TContext\u上下文;
[…UoW默认实现..]
公共空间处置()
{
_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>();
}
}
公共静态类SimpleInjectorWebAPI初始值设定项
{
///初始化容器并将其注册为Web API依赖项解析器。
公共静态void Initialize()
{
var container=新容器();
container.Options.DefaultScopedLifestyle=新的WebApiRequestLifestyle();
初始化容器(容器);
容器.RegisterWebApp控制器(全局配置.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver=
新的SimpleInjectorWebApidencyResolver(容器);
}
私有静态void InitializeContainer(容器)
{
//例如:
容器。寄存器(类型(IUnitOfWork)、类型(UnitOfWork)、生活方式。范围);
container.RegisterWebApiRequest();
container.RegisterWebApiRequest();
}
}
当我尝试注册此类型和其他服务时,会收到以下警告:
-[生活方式不匹配]UnitOfWork
(Web API请求)取决于CustomerContext(瞬态)
-[一次性瞬态组件]CustomerContext注册为瞬态,但实现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...]
}
}
[RoutePrefix(“客户/银行”)]
公共类BankController:ApicController
{
专用只读IBankService\u银行服务;
公共银行控制器(IBankService银行服务)
{
_银行服务=银行服务;
}
[路线]
公共IEnumerable Get()
{
var result=_bankService.GetBanks();
[…映射和返回…]
}
}
我已经尝试压制这些警告:
Registration registration = container.GetRegistration(typeof(IUnitOfWork<>)).Registration;
registration.SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent, "Dispose called by application code");
Registration Registration=container.GetRegistration(typeof(IUnitOfWork)).Registration;
registration.SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent,“由应用程序代码调用的Dispose”);
…但我收到了一个无效手术的例外
您对如何注册有何想法?您面临的问题是没有为
CustomerContext
添加注册
因为CustomerContext
有一个默认构造函数,所以Simple Injector能够为您自动关联此依赖项。但是,当Simple Injector在第一次调用GetInstance
时对此进行注册时,容器除了使用默认的生活方式注册此servicetype之外别无选择。然而,简单喷油器的默认生活方式是:瞬态
换句话说,您收到的诊断警告是正确的,因为CustomerContext
实际上已注册为Transient
要解决此问题,请将CustomerContext
的注册添加为:
container.Register<CustomerContext>(Lifestyle.Scoped);
container.Register(lifesture.Scoped);
您可以删除警告抑制的配置,因为这些“警告”是实际问题
此时实际上有第三个诊断警告可用。您可以阅读有关容器注册类型
警告的信息。此诊断警告通知您,对象图中需要的类型不属于配置的一部分。这是一个信息性警告,因此在验证容器时不会作为异常抛出。使用信息类的原因是,对于一个可以是瞬态的简单类来说,这一点都没有问题,而且在一些有效的用例中,您无法在编译时注册所有类
但是在容器中注册所有需要的类型是一种好的做法,因为在这种情况下,容器完全知道所有类,因此能够尽可能地验证配置
这是一个好做法的第二个原因是因为每个DI容器都有不同的“默认生活方式”。简单喷油器默认为Transient
,而其他喷油器默认为Singleton
。如果您以后要交换DI容器,可能会导致应用程序在运行时失败,因为某个组件突然变成Singleton
您在抑制警告时收到InvalidOperationException
的原因是容器(尚未)无法抑制打开泛型类型上的警告。在这种情况下,这是一件好事,因为你必须来寻求帮助
如果您成功地抑制了这些警告,您很快就会发现自己正在调试奇怪的问题
因为如果您的DbContext
是Transient
,会发生什么
每个依赖于此DbContext
的服务/commandhandler/queryhandler/等将获得不同的服务!!这可能导致以下情况:
- 您可以使用queryhandler/repository或任何服务从数据库中获取记录
- 您将在另一个服务/commandhandler中使用一些新信息更新实体,该服务/commandhandler本身依赖于
DbContext
,因此是一个不同的实例
- 您可以在另一个类中调用
DbContext.SaveChanges()
,也可以使用它自己的DbContext实例,例如SaveChangesCommandHandlerDecorator
。因为这DbContext
没有跟踪