C# 注册通用工作单元时出错<&燃气轮机;与国际奥委会

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..]

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

 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
    没有跟踪