我对业务层使用依赖注入,其中包含服务,例如下面的示例:
public class MyService : IMyService
{
private IMyDbContext DbContext;
public MyService(IMyDbContext dbContext)
{
this.DbContext = dbContext;
}
public DoSomething(int id)
{
// Use the business layer for something
var user = this.DbContext.Set<User>().Find(id);
}
}
如您所见,我的服务将我的Entity Framework DbContext作为依赖项。我使用Ninject作为我的IoC容器,但我认为这适用于任何。
ASP.NET MVC网站配置
对于我的ASP.NET网站,我使用Ninject配置每个请求创建一个IMyDbContext
,每个请求只需要一个IMyService
实例 - 所以它很好,简单。
Windows服务配置
我希望对它进行配置,以便对于我的Window Service的每次迭代,我都不必新增&#39;我为每次迭代提供的服务。
我想要进行以下配置:
当我在两个不同项目之间共享服务时,如何实现这一目标。
我的朋友建议我为我的IDbContext
使用工厂,如果我不想在我的ASP.NET应用程序中继续使用Per Request Scope
,那就没关系了 - 但我确实如此。我不确定我是否可以将工厂配置为每次为此目的返回相同的实例,并为我的Windows服务中的每个请求添加一个新实例。
问题是,例如,如果我现在使用工厂(对于每次调用DoSomething()
都需要新实例的Windows服务):
public class MyService : IMyService
{
private IMyContextFactory DbContextFactory;
public MyService(IMyContextFactory dbContextFactory)
{
this.DbContextFactory = dbContextFactory;
}
public DoSomething(int id)
{
// Get instance of the db for use
var dbContext = this.DbContextFactory.GetInstance();
// Use the business layer for something
var user = dbContext.Set<User>().Find(id);
}
}
正如您所看到的,我现在必须添加一行代码才能使用工厂。
这不再适用于我想要使用DbContext的单个(每个请求)实例的网站。
我需要一个适用于这两种方案的配置,因为我要共享代码库。
对于配置kernel
绑定的两个项目,我已经有了一个boostrapper,它只是如何我在共享代码库时为不同场景配置绑定。
答案 0 :(得分:1)
因为MVC和Windows服务是两个不同的主机,对注入的依赖项的生命周期有不同的要求,所以它们应该有自己的Ninject注册。 MVC将以不同于Windows服务主机的方式定义IMyService。
如果不可能,并且您必须为两台主机使用相同的ninject注册码,那么应用程序的类型可以是一个命名的discrimator来创建IMyService的实例。
kernel.Bind<IMyService>().To<MyService>().Named("MVC"); // add lifetime thingy
kernel.Bind<IMyService>().To<MyService>().Named("WindowsService"); // add lifetime
// usage
var iammvc= kernel.Get<IMyService>("MVC");
如果Ninject获得&#34; MVC&#34;,你可以单向设置它,如果它得到&#34; WindowsService&#34;,你可以用不同的方式设置它。
选项1通常是首选,因为MVC和Windows服务具有不同的执行上下文(Http Request n all),并且更容易独立地控制它们的依赖项。
答案 1 :(得分:0)
我告诉我工厂扩展使用IResolutionRoot
来解决依赖关系。
这意味着当工厂创建实例时,它会根据绑定中现有的类型配置创建实例。
如果我设置了以下绑定:
Kernel.Bind<IMyDbContext>().To<MyDbContext>().InRequestScope();
当我打电话给工厂时,它会为每次调用工厂返回相同的实例:
// All of these will return the same DbContext
var dbContext1 = this.DbContextFactory.Create();
var dbContext2 = this.DbContextFactory.Create();
var dbContext3 = this.DbContextFactory.Create();
然而,对于我的Window Service,我希望它每次都是一个新实例,我将DbContext设置为瞬态:
Kernel.Bind<IMyDbContext>().To<MyDbContext>().InTransientScope();
然后我可以在我的服务中致电工厂:
// This will return a new instance of my DbContext every time
var dbContext1 = this.DbContextFactory.Create();
var dbContext2 = this.DbContextFactory.Create();
var dbContext3 = this.DbContextFactory.Create();
这是工厂的绑定:
Kernel.Bind<IMyDbContextFactory>().ToFactory();
这是工厂的界面:
public interface IMyDbContextFactory
{
IMyDbContext Create();
}