BBa*_*r42 4 .net c# dependency-injection inversion-of-control simple-injector
我有一个项目使用Unity完美运行.我尝试切换到使用Simple Injector,现在没有任何更改保存在我的数据库中.我认为这与注册组件的生命周期有关.这是Unity容器注册:
private IUnityContainer GetUnityContainer()
{
IUnityContainer container = new UnityContainer()
.RegisterType<IDatabaseFactory, DatabaseFactory>(
new HttpContextLifetimeManager<IDatabaseFactory>())
.RegisterType<IUnitOfWork, UnitOfWork>(
new HttpContextLifetimeManager<IUnitOfWork>())
.RegisterType<ICategoryRepository, CategoryRepository>(
new HttpContextLifetimeManager<ICategoryRepository>())
.RegisterType<ICategoryService, CategoryService>(
new HttpContextLifetimeManager<ICategoryService>());
return container;
}
Run Code Online (Sandbox Code Playgroud)
这是新的Simple Injector注册.
container.Register<IDatabaseFactory, DatabaseFactory>();
container.Register<IUnitOfWork, UnitOfWork>();
container.Register<ICategoryRepository, CategoryRepository>();
container.Register<ICategoryService, CategoryService>();
Run Code Online (Sandbox Code Playgroud)
我不确定HttpContextLifetimeManagerSimple Injector 是如何发挥作用的.MVC是统一示例的客户端,但我正在改为WPF项目和Simple Injector.任何建议都非常感谢.谢谢.
@Steven.谢谢你的评论.我刚刚发现,因为我的RepositoryBase和我的UnitOfWork在我需要使用的构造函数中注入了一个IDatabaseFactory container.RegisterSingle<IDatabaseFactory, DatabaseFactory>().这解决了一个问题.我的生命仍然有问题.由于我的消费应用程序是WPF,RegisterPerWebRequest将如何工作?
我的项目有一个DataLayer >> BusinessLayer >> WcfService >> WPF前端.简单的Injector在WcfService项目上设置,业务层有Boostrapper在那里注册项目.截至目前,我的WPF客户端将GetAllCountries()并显示在网格中.如果我更改了一个名称并尝试更新,我会得到"ObjectStateManager中已存在具有相同键的对象.ObjectStateManager无法跟踪具有相同键的多个对象." 错误.我做了一些调试,发现在WPF客户端中调用GetCountries服务之后,当我回去尝试更新时,我看到所有国家都通过dbContext.ChangeTracker.Entries()附加到上下文.此时我应该没有跟踪任何实体,因为我的上下文应该在第一个工作单元之后被处理掉.
在一个MVC应用程序中,RegisterPerWebRequest修复了这个问题,但WPF的等价物是什么?我现在要安装扩展程序并尝试它但我觉得这不是我正在寻找的解决方案..或者是它?再次感谢您的帮助.
好.我做了一些挖掘,找到了一个有效的解决方案.我只是不确定它是不是正确的.无论如何,现在在我的BLL中有一个注册东西的引导程序,我可以像这样注册:
container.RegisterPerWcfOperation<IDatabaseFactory, DatabaseFactory>();
container.RegisterPerWcfOperation<IUnitOfWork, UnitOfWork>();
container.RegisterPerWcfOperation<ICountryRepository, CountryRepository>();
Run Code Online (Sandbox Code Playgroud)
这给了我正在寻找的东西.只创建了一个DatabaseFactory实例,因此我的存储库和工作单元就像它们应该的那样共享它.此外,在客户端上的GetCountries()之后,当我第二次调用服务执行和更新时,我检查dbContext.ChangeTracker.Entries()并查看没有跟踪的实体,这是正确的.我现在可以附加,设置修改,并调用SaveChanges而不会出现重复键错误.这看起来好吗?谢谢.
RegisterSimple Injector寄存器类型的重载使用瞬态生活方式(这意味着没有缓存).每次请求实例(或注入实例)时,都会创建一个新实例.在Unity,这是一样的; 默认的生活方式是短暂的.
似乎用Per Web Request生活方式注册这些类型是非常必要的.当执行那些提交的类IUnitOfWork获得与实际进行更改的类不同的实例时,更改未提交到数据库并不奇怪IUnitOfWork.
简单的喷油器的等同于Unity的HttpContextLifetimeManager是WebRequestLifestyle.这种生活方式不是核心库的一部分,但可以作为NuGet包使用.
在项目中包含此项后,您可以进行以下注册:
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
container.Register<IDatabaseFactory, DatabaseFactory>(Lifestyle.Scoped);
container.Register<IUnitOfWork, UnitOfWork>(Lifestyle.Scoped);
container.Register<ICategoryRepository, CategoryRepository>(Lifestyle.Scoped);
container.Register<ICategoryService, CategoryService>(Lifestyle.Scoped);
Run Code Online (Sandbox Code Playgroud)
或等效的:
Lifestyle lifestyle = new WebRequestLifestyle();
container.Register<IDatabaseFactory, DatabaseFactory>(lifestyle);
container.Register<IUnitOfWork, UnitOfWork>(lifestyle);
container.Register<ICategoryRepository, CategoryRepository>(lifestyle);
container.Register<ICategoryService, CategoryService>(lifestyle);
Run Code Online (Sandbox Code Playgroud)
默认行为WebRequestLifestyle是在Web请求结束时处置创建的实例.无需特殊注册(Simple Injector HttpModule在应用程序启动时为您提供连接).
我很抱歉没有把你的问题读到最后一行.我错过了你想使用WPF客户端配置它的事实.
您可能知道,由于您的客户端是与WCF服务不同的应用程序,因此您的系统中将有两个组合根 ; 一个用于客户端,一个用于服务.他们的注册可能会大不相同.从Simple Injector v4.1开始,对于WCF服务,您确实需要AsyncScopedLifestyle,或者当您遵循dotnetjunkie/solidservices中的参考体系结构时,您会发现使用ThreadScopedLifestyle并在两种Execute方法中明确定义范围.
我发现在两层应用程序(客户端 - >数据库)的客户端中管理对象的生命周期相当困难,因为很难为某个范围定义一个工作单元.由于您使用的是命令/处理程序+查询/处理程序方法,因此事情将变得如此简单.客户端不会有任何工作单元.就在服务器上.您的演示者可以依赖于几个IQueryHandler<TQuery, TResult>和ICommandHandler<TCommand>接口,您就完成了.查询不会更改状态,命令应该是原子操作.换句话说,仅在执行命令的边界内需要工作单元.
| 归档时间: |
|
| 查看次数: |
3956 次 |
| 最近记录: |