C# EventFlow自定义输出中的依赖项注入

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

我正在使用EventFlow跟踪ETW事件。为此,我创建了一个充当侦听器的ASP Net核心服务。我已经在配置文件中配置了自己的自定义输出。以下是我的输出和OutputFactory类:

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();

        //...
    }
}