在.NET Core内置DI容器中为AddScoped服务实现自定义处理

时间:2019-06-07 18:51:16

标签: c# azure .net-core azure-functions dispose

我想使用AddScoped方法在ServiceCollection中注册TelemetryClient,并在处置客户端时调用Flush。在作用域完成显式调用后,我无权访问TelemetryClient,并且我需要将TelemetryClient传递给第三方方法的方法,因此我不能使用包装器。

我在Azure Functions中使用.Net Core的内置Di容器。

我正在这样注册它:

services.AddScoped(x =>
            {
                return new TelemetryClient();
            });

我想在Autofac中使用类似OnRelease的方法,因此我可以像下面这样注册它。请注意对OnRelease的调用:

services.AddScoped(x =>
            {
                return new TelemetryClient();
            }).OnRelease(x=>
            {
                x.Flush();
            });

1 个答案:

答案 0 :(得分:1)

您可以像这样包装TelemetryClient

public interface ILogsStuff
{
    void LogSomething(string message);
}

public class TelemetryClientLogger : ILogsStuff, IDisposable
{
    private readonly TelemetryClient _telemetryClient;

    public TelemetryClientLogger(TelemetryClient telemetryClient)
    {
        _telemetryClient = telemetryClient;
    }

    public void LogSomething(string message)
    {
        _telemetryClient.TrackTrace(message);
    }

    public void Dispose()
    {
        _telemetryClient.Flush();
    }
}

还有一个额外的好处,那就是,无论您将其注入哪个类,都不会直接依赖于TelemetryClient。您可以定义一个接口,该接口描述要使用客户端的任何对象,并且如果需要,可以更轻松地模拟和替换为其他实现。

suggestion was made使TelemetryClient实现IDisposable并在处置时使其调用Flush(),这是推荐的解决方案。


问题的更新内容如下:

  

我需要将TelemetryClient传递给第三方方法,这样我才能使用包装器。

这会有所改变,因为现在的目的不是使用 TelemetryClient,而是解决它,然后将其传递给第三方库的方法。之所以如此,是因为它意味着该库强制使用它的代码对TelemetryClient具有严格的依赖性,并且可能无法按预期方式处理该客户端。

这时仍然有解决方案,但是它们都是丑陋的,因为它们是解决不应该存在的怪异问题的解决方案(不是由您的代码创建的)。

如果要将TelemetryClient传递给方法,该方法将写入该方法,然后必须对其进行刷新,为什么那个库不刷新它?

您可以通过在执行过程中将TelemetryClient传递给方法,然后在方法执行后刷新客户端来解决该问题。

CallSomeMethod(someArgument, _telemtryClient);
telemetryClient.Flush();

或者,为了使结果更接近您的问题,您可以这样做,虽然可以获得结果,但是仍然很尴尬和奇怪:

public class TelemetryClientWrapper : IDisposable
{
    private readonly TelemetryClient _telemetryClient;

    public TelemetryClientWrapper(TelemetryClient telemetryClient)
    {
        _telemetryClient = telemetryClient;
    }

    public TelemetryClient Client => _telemetryClient;

    public void Dispose()
    {
        _telemetryClient.Flush();
    }
}

您可以注入此类并将其传递给库的方法,如下所示:

CallSomeMethod(someArgument, _telemtryClientWrapper.Client);

现在的问题是,即使不使用它,您的类也对TelemetryClient 有严格的依赖关系,所有这些都可以修复其他库(大概是)。不能正确处理该客户。

说了这么多,也许是在您的场景this is the answer中:

  

内置服务容器旨在满足框架和大多数消费者应用程序的需求。我们建议您使用内置容器,除非您需要它不支持的特定功能。内置容器中找不到第三方容器支持的一些功能:

换句话说,如果您需要Autofac的功能,则可以将still use AutofacIServiceCollection一起使用。