gpt4 book ai didi

c# - StructureMap .Net Core Windows 服务嵌套容器

转载 作者:太空狗 更新时间:2023-10-29 21:48:41 25 4
gpt4 key购买 nike

有很多文章讨论如何在 ASP.NET Core 中使用 Structure Map,但讨论控制台应用程序或 Windows 服务的文章并不多。 ASP.Net Core 中的默认行为是 StructureMap 为每个 HTTPRequest 创建一个嵌套容器,以便每个 HTTP 请求只实例化一个具体类。

我正在使用 PeterKottas.DotNetCore.WindowsService nuget 包创建 .Net Core Windows 服务。我使用这篇文章设置 StructureMap:https://andrewlock.net/using-dependency-injection-in-a-net-core-console-application/

我的 Windows 服务是在计时器上设置的,每 X 秒执行一次操作。我希望这些操作中的每一个都使用类似于 ASP.NET 的嵌套容器。换句话说,我希望在轮询传递完成后处理为轮询传递 #1 创建的所有内容。当 polling pass #2 开始时,我希望对象的所有新实例都被实例化。但是,在单个轮询过程中,我只想为每个对象创建一个实例。

执行此操作的正确方法是什么?

这是我的程序类

public class Program
{
public static ILoggerFactory LoggerFactory;
public static IConfigurationRoot Configuration;

static void Main(string[] args)
{
var applicationBaseDirectory = AppContext.BaseDirectory;
string environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

if (string.IsNullOrWhiteSpace(environment))
throw new ArgumentNullException("Environment not found in ASPNETCORE_ENVIRONMENT");

ConfigureApplication(applicationBaseDirectory, environment);
var serviceCollection = ConfigureServices();
var serviceProvider = ConfigureIoC(serviceCollection);
ConfigureLogging(serviceProvider);

var logger = LoggerFactory.CreateLogger<Program>();
logger.LogInformation("Starting Application");

ServiceRunner<IWindowsService>.Run(config =>
{
var applicationName = typeof(Program).Namespace;
config.SetName($"{applicationName}");
config.SetDisplayName($"{applicationName}");
config.SetDescription($"Service that matches Previous Buyers to Vehicles In Inventory to Fine Upgrade Opportunities.");
config.Service(serviceConfig =>
{
serviceConfig.ServiceFactory((extraArgs, microServiceController) =>
{
return serviceProvider.GetService<IWindowsService>();
});
serviceConfig.OnStart((service, extraArgs) =>
{
logger.LogInformation($"Service {applicationName} started.");
service.Start();
});
serviceConfig.OnStop((service =>
{
logger.LogInformation($"Service {applicationName} stopped.");
service.Stop();
}));
serviceConfig.OnError(error =>
{
logger.LogError($"Service {applicationName} encountered an error with the following exception:\n {error.Message}");
});
});
});
}

private static void ConfigureApplication(string applicationBaseDirectory, string environment)
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);

var builder = new ConfigurationBuilder()
.SetBasePath(applicationBaseDirectory)
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{environment}.json", optional: true)
.AddEnvironmentVariables();

Configuration = builder.Build();
}

private static IServiceCollection ConfigureServices()
{
var serviceCollection = new ServiceCollection().AddLogging().AddOptions();

serviceCollection.AddDbContext<JandLReportingContext>(options => options.UseSqlServer(Configuration.GetConnectionString("JandLReporting")), ServiceLifetime.Transient);
//serviceCollection.AddDbContext<JLMIDBContext>(options => options.UseSqlServer(Configuration.GetConnectionString("JLMIDB")), ServiceLifetime.Scoped);
serviceCollection.Configure<TimerSettings>(Configuration.GetSection("TimerSettings"));
serviceCollection.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

return serviceCollection;
}

private static IServiceProvider ConfigureIoC(IServiceCollection serviceCollection)
{
//Setup StructureMap
var container = new Container();

container.Configure(config =>
{
config.Scan(scan =>
{
scan.AssemblyContainingType(typeof(Program));
scan.AssembliesFromApplicationBaseDirectory();
scan.AssembliesAndExecutablesFromApplicationBaseDirectory();
scan.WithDefaultConventions();
});

config.Populate(serviceCollection);
});

return container.GetInstance<IServiceProvider>();
}

private static void ConfigureLogging(IServiceProvider serviceProvider)
{
LoggerFactory = serviceProvider.GetService<ILoggerFactory>()
.AddConsole(Configuration.GetSection("Logging"))
.AddFile(Configuration.GetSection("Logging"))
.AddDebug();
}
}

这是我的 WindowsService 类:

public class WindowsService : MicroService, IWindowsService
{
private readonly ILogger _logger;
private readonly IServiceProvider _serviceProvider;
private readonly TimerSettings _timerSettings;

public WindowsService(ILogger<WindowsService> logger, IServiceProvider serviceProvider, IOptions<TimerSettings> timerSettings)
{
_logger = logger;
_serviceProvider = serviceProvider;
_timerSettings = timerSettings.Value;
}

public void Start()
{
StartBase();

Timers.Start("ServiceTimer", GetTimerInterval(), async () =>
{
await PollingPassAsyc();
},
(error) =>
{
_logger.LogCritical($"Exception while starting the service: {error}\n");
});
}

private async Task PollingPassAsyc()
{
using (var upgradeOpportunityService = _serviceProvider.GetService<IUpgradeOpportunityService>())
{
await upgradeOpportunityService.FindUpgradeOpportunitiesAsync();
}
}

private int GetTimerInterval()
{
return _timerSettings.IntervalMinutes * 60 * 1000;
}

public void Stop()
{
StopBase();
_logger.LogInformation($"Service has stopped");
}
}

最佳答案

Microsoft.Extensions.DependencyInjection 命名空间中的IServiceProvider 有扩展方法CreateScope。它所做的是从负责创建新作用域的当前 DI 容器解析特殊接口(interface) (IServiceScopeFactory),并使用该工厂创建新作用域。 StructureMap 注册此接口(interface)的实现,因此当您调用 CreateScope - StructureMap 将创建嵌套容器。示例用法:

using (var scope = _serviceProvider.CreateScope()) {
// use scope.ServiceProvider, not _serviceProvider to resolve instance
var service = scope.ServiceProvider.GetService<IUpgradeOpportunityService>‌​();
}

关于c# - StructureMap .Net Core Windows 服务嵌套容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47640296/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com