c# - ASP.NET Core 不会用 StructureMap 替换 IoC
问题描述
我的应用程序基于 ASP.NET Core 2.1 和 .NET Core 2.1(从 2.2 降级)通用主机作为 Windows 服务。因此,IHostBuilder
首先与其他服务和框架一起启动,然后(如果角色允许)使用IWebHostBuilder
所有WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().StartAsync()
. 二级 WebHost 是另一回事;它已初始化并且可以工作,但我还没有检查 IoC 更换是否与通用主机有同样的问题。
现在,通用主机初始化:
new HostBuilder().ConfigureServices((hostContext, services) =>
{
services.AddHostedService<LifetimeService>(); // Gets launched when host is up
var container = ContainerBuilder.BuildBaseContainer(services, new WorkingPath());
services.AddSingleton<IContainer>(container);
services.AddStructureMap(); // Has no effect
});
IContainer 初始化:
public static Container BuildBaseContainer(IServiceCollection services, IWorkingPath workingPath)
{
var container = new Container();
container.Configure(config =>
{
config.Scan(scan =>
{
workingPath.OwnLoadedAssemblies.Where(asm => !asm.IsDynamic).ForEach(scan.Assembly);
scan.LookForRegistries();
scan.AddAllTypesOf<IPlatformService>();
});
config.For<IContainer>().Use(() => container);
config.Populate(services);
});
container.AssertConfigurationIsValid();
return container;
}
问题出在该注册托管服务的构造函数中(或其他任何地方)
public LifetimeService(IEnumerable<IPlatformService> services,
IServiceProvider sp, IContainer c)
{
var inCollection = services.Any();
var inContainer = c.TryGetInstance<IPlatformService>() != default;
var inProvider = sp.GetRequiredService<IPlatformService>() != default;
}
ps: IServiceProvider 和 IContainer 仅用于演示,我只需要'services'
当在我得到时LifetimeService
初始化是真的是真的是真的是container.AssertConfigurationIsValid()
inCollection
inContainer
inProvider
IServiceProvider
StructureMapServiceProvider
实际LifetimeService
执行表明
inCollection
is false
inContainer
is true
inProvider
is false
IServiceProvider
isServiceProviderEngineScope
我不打算将 IServiceProvider 或 IContainer 传递给构造函数,但似乎依赖关系是使用 IServiceProvider 而不是 IContainer 解决的,并且我得到空值。像这样愚蠢的事情sp.GetRequiredService<IContainer>().TryGetInstance<IPlatformService>()
确实有效。
有一些使用 WebHost 和 Startup 类的快乐路径示例,其中注入应该正常工作。似乎与通用主机无关……有一天它可能会取代 WebHost,但鲜为人知且未被广泛使用。好吧,也可能是由于 .NET Core 版本降级,但不太可能。我还尝试在 ConfigureServices() 期间从 IContainer 替换 IServiceProvider 和 IServiceScopeFactory ,但没有成功。我的想法是将内部容器替换或转发到 StructureMap。我可能会误解这应该如何工作......
有没有人成功尝试“嫁接”通用主机和外部 IoC?
解决方案
我已经解开了谜题!最后,根据一个过于简化的示例(https://github.com/aspnet/Hosting/blob/master/samples/GenericHostSample/ProgramFullControl.cs),我不得不将HostBuilder
初始化更改为
new HostBuilder()
.UseServiceProviderFactory(new StructureMapContainerFactory(workingPath))
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<LifetimeService>();
});
并介绍提供者工厂本身
public class StructureMapContainerFactory : IServiceProviderFactory<IContainer>
{
private readonly IWorkingPath workingPath;
// pass any dependencies to your factory
public StructureMapContainerFactory(IWorkingPath workingPath)
{
this.workingPath = workingPath;
}
public IContainer CreateBuilder(IServiceCollection services)
{
services.AddStructureMap();
return ContainerBuilder.BuildBaseContainer(services, workingPath);
}
public IServiceProvider CreateServiceProvider(IContainer containerBuilder)
{
return containerBuilder.GetInstance<IServiceProvider>();
}
}
现在内部容器被 StructureMap 替换并解析IServiceProvider
为LifetimeService
is 类型StructureMapServiceProvider
。
推荐阅读
- windows - 启动 Web sphere 8.5 应用程序服务器时出错
- python - 如何创建一个动态的嵌套 json,可以在之后存储和重新加载和编辑?
- php - 搜索 PHP 示例新的条带“结帐”集成 stripe-php
- java - 如何将 Java 注释添加到 JNI SWIG API?
- google-sheets - 计算 Google 表格单元格中的换行数
- javascript - 用for循环锻炼
- lua - lua 尝试调用方法“len”(一个 nil 值)
- python - 我的代码的 browser = Browser('firefox') 部分存在问题
- sql - Oracle 字符串转换
- typescript - 如何避免在将来填充的属性上出现“对象可能为空”警告