有很多文章讨论如何将结构图与ASP.NET Core一起使用,但谈论控制台应用程序或Windows服务并不是很多。 ASP.Net Core中的默认行为是StructureMap为每个HTTPRequest创建一个嵌套容器,以便每个HTTP请求只对实例化一个具体类。
我正在使用PeterKottas.DotNetCore.WindowsService nuget包创建.Net核心Windows服务。我使用这篇文章设置了StructureMap:https://andrewlock.net/using-dependency-injection-in-a-net-core-console-application/
我的Windows服务是在Timer上设置的,每X秒执行一次操作。我希望这些操作中的每一个都使用类似于ASP.NET的嵌套容器。换句话说,我希望在轮询传递完成后处理为轮询传递#1创建的所有内容。当轮询#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");
}
}
答案 0 :(得分:3)
TEST_UNDECLARED_OUTPUTS_DIR
命名空间中的CreateScope
有扩展方法IServiceProvider
。它的作用是从当前DI容器中解析特殊接口(Microsoft.Extensions.DependencyInjection
),该容器负责创建新作用域,并使用此工厂创建新作用域。 StructureMap注册了这个接口的实现,所以当你调用IServiceScopeFactory
时 - StructureMap会创建嵌套容器。样品用法:
CreateScope