在依赖注入的时候有时候我们需要创建工厂类或者Func<>来创建需要的类,但是这样有时候不太方便,除了使用上面的方式外,我们还可以自己创建Scope。
(在.net 程序里面我们最经常需要 用到的一个新的 Ef core 的 DbContext.比如避免 DbContext的实体缓存问题 因为项目架构,还有时间成本。我们很难去改动旧的代码。 所以也只能靠创建 Scope的方式来解决它了)
代码如下
public class Worker
{
private readonly IMessageWriter _messageWriter;
private readonly IServiceProvider _sp;
public Worker(IMessageWriter messageWriter, IServiceProvider sp)
{
_messageWriter = messageWriter;
_sp = sp;
}
public async Task ExecuteAsync()
{
_messageWriter.Write($"Worker running at: {DateTimeOffset.Now}");
for (int i = 0; i < 10; i++)
{
//使用Scope来获取类
using (var scope = _sp.CreateScope())
{
var innerWorker = scope.ServiceProvider.GetService<InnerWorker>();
}
}
}
}
上面的这种写法,可以让我们旧代码可以继续使用,而不需要改造成Func<>或者工厂方法。 但是这种写法,会让我们写单元测试比较麻烦。 可以使用下面的这个方法来Mock.
public static Mock<IServiceProvider> GetProvider()
{
var serviceProvider = new Mock<IServiceProvider>();
var serviceScope = new Mock<IServiceScope>();
serviceScope.Setup(x => x.ServiceProvider).Returns(serviceProvider.Object);
var serviceScopeFactory = new Mock<IServiceScopeFactory>();
serviceScopeFactory
.Setup(x => x.CreateScope())
.Returns(serviceScope.Object);
serviceProvider
.Setup(x => x.GetService(typeof(IServiceScopeFactory)))
.Returns(serviceScopeFactory.Object);
return serviceProvider;
}
//进行Mock
var serviceProvider = ServiceProviderHelper.GetProvider();
serviceProvider.Setup(it => it.GetService(typeof(IXXInteface))).Returns(customerService.Object);