C# EventFlow自定义输出中的依赖项注入
我正在使用EventFlow跟踪ETW事件。为此,我创建了一个充当侦听器的ASP Net核心服务。我已经在配置文件中配置了自己的自定义输出。以下是我的输出和OutputFactory类:C# EventFlow自定义输出中的依赖项注入,c#,asp.net-core,dependency-injection,azure-service-fabric,event-flow,C#,Asp.net Core,Dependency Injection,Azure Service Fabric,Event Flow,我正在使用EventFlow跟踪ETW事件。为此,我创建了一个充当侦听器的ASP Net核心服务。我已经在配置文件中配置了自己的自定义输出。以下是我的输出和OutputFactory类: class CustomOutput : IOutput { public Task SendEventsAsync(IReadOnlyCollection<EventData> events, long transmissionSequenceNumber, CancellationTok
class CustomOutput : IOutput
{
public Task SendEventsAsync(IReadOnlyCollection<EventData> events, long transmissionSequenceNumber, CancellationToken cancellationToken)
{
foreach(var e in events)
{
//...;
}
return Task.CompletedTask;
}
}
class CustomOutputFactory : IPipelineItemFactory<CustomOutput>
{
public CustomOutput CreateItem(IConfiguration configuration, IHealthReporter healthReporter)
{
return new CustomOutput();
}
}
配置文件eventFlowConfig.json中引用了输出和工厂输出类型:
"extensions": [
{
"category": "outputFactory",
"type": "CustomOutput",
"qualifiedTypeName": "MyProyect.Service.MyApp.SqlOutputFactory, MyProyect.Service.MyApp"
}
]
参考:
因此,实例是在我的程序类的主方法中创建的,也就是说,在调用我的启动配置方法之前
如果容器在实例化时仍然不存在,我如何从输出类访问依赖项容器服务
目前,我已经创建了一个IServiceCollection类型的静态属性,并从启动配置方法(使用setter注入)进行了设置。我不喜欢这个解决方案,因为我不应该使用静态访问服务,但我不知道其他解决方案。这是有效的做法吗
class CustomOutput : IOutput
{
public static IServiceCollection Services { get; set; }
public Task SendEventsAsync(IReadOnlyCollection<EventData> events, long transmissionSequenceNumber, CancellationToken cancellationToken)
{
var sp = Services.BuildServiceProvider();
var loggerFactory = sp.GetService<ILoggerFactory>();
logger = loggerfactory.CreateLogger<CustomOutput>();
var repository = serviceProvider.GetService<IMyRepository>();
foreach (var e in events)
{
logger.LogDebug("event...");
repository.SaveEvent(e);
//...;
}
return Task.CompletedTask;
}
}
public class Startup
{
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//..
CustomOutput.Services = services;
//..
}
}
类CustomOutput:IOOutput
{
公共静态IServiceCollection服务{get;set;}
公共任务SendEventsAsync(IReadOnlyCollection事件、长传输序列号、取消令牌取消令牌)
{
var sp=Services.BuildServiceProvider();
var loggerFactory=sp.GetService();
logger=loggerfactory.CreateLogger();
var repository=serviceProvider.GetService();
foreach(事件中的var e)
{
logger.LogDebug(“事件…”);
SaveEvent(e);
//...;
}
返回Task.CompletedTask;
}
}
公营创业
{
//使用此方法向容器中添加服务。
public void配置服务(IServiceCollection服务)
{
//..
CustomOutput.Services=服务;
//..
}
}
使用而不是当前正在实现的服务定位器模式将是更好的选择。目标框架的可扩展性的限制使得这一点很困难
只留下静态访问器作为可能的解决方案的扩展点
由于CustomOutput
只创建一次,因此在本设计中,遵循单例模式应该是可行的
public class CustomOutput : IOutput {
private static Lazy<CustomOutput> instance =
new Lazy<CustomOutput>(() => return new CustomOutput());
private Lazy<ILogger> logger;
private Lazy<IMyRepository> repository;
private CustomOutput() { }
public static CustomOutput Instance {
get {
return instance.Value;
}
}
public void Configure(Lazy<ILogger> logger, Lazy<IMyRepository> repository) {
this.logger = logger;
this.repository = repository
}
public Task SendEventsAsync(IReadOnlyCollection<EventData> events, long transmissionSequenceNumber, CancellationToken cancellationToken) {
//TODO: Add null check and fail if not already configured.
foreach (var e in events) {
logger.Value.LogDebug("event...");
repository.Value.SaveEvent(e);
//...;
}
return Task.CompletedTask;
}
}
public class CustomOutputFactory : IPipelineItemFactory<CustomOutput> {
public CustomOutput CreateItem(IConfiguration configuration, IHealthReporter healthReporter) {
return CustomOutput.Instance;
}
}
然后从启动
调用
public class Startup {
//...
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
//...
services.ConfigureCustomOutput();
//...
}
}
IServiceCollection
只能生成一次。在for循环中重复执行。显示有关需要哪些服务以及如何使用这些服务的更多详细信息。这可能是一个错误。你是对的,IServiceCollection必须在循环之外。使用具体服务进行后期更新。在调用启动方法之前创建CustomOutput。EventFlow在Program类的main方法中实例化CustomOutput。容器仍然不存在。我不能使用构造函数注入服务。@Alpha75显示与集成.net内核的方式相关的主要方法。创业公司。让我们看看是否可以找到一个变通的main方法。@Alpha75我仍在查看存储库,但您应该看看,我也曾想过解决属性集上的服务。在我看来,最好像你那样推迟审理。
public static class CustomOutputServiceCollectionExtensions {
public IServiceCollection ConfigureCustomOutput(this IServiceCollection services) {
services.AddTransient<IMyRepository, MyRepository>();
var logger = new Lazy<ILogger>(() => {
var sp = services.BuildServiceProvider();
return sp.GetService<ILogger<CustomOutput>>();
});
var repository = new Lazy<IMyRepository>(() => {
var sp = services.BuildServiceProvider();
return sp.GetService<IMyRepository>();
});
CustomOutput.Instance.Configure(logger, repository);
return services;
}
}
public class Startup {
//...
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
//...
services.ConfigureCustomOutput();
//...
}
}