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

Implement custom dispose for AddScoped services in .NET Core built-in DI Container

我想使用 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();
            });

您可以像这样包装 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();
    }
}

还有一个额外的好处,那就是无论您将其注入什么 class,都不会直接依赖于 TelemetryClient。您可以定义一个接口来描述您想要使用客户端的任何内容,如果需要的话,它更容易模拟和替换为其他实现。

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


您的问题更新为:

I need to pass the TelemetryClient to a method of a third party method so I cannot use a wrapper.

这有点改变,因为现在的目的不是 使用 TelemetryClient 而是解析它然后将其传递给第 3 方的方法图书馆。这很奇怪,因为这意味着该库强制使用它的代码对 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();
    }
}

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

CallSomeMethod(someArgument, _telemtryClientWrapper.Client);

现在的问题是你的 class 对 TelemetryClient 有硬依赖,即使它不使用它 ,所以它可以修复其他图书馆(大概)没有正确地处理那个客户。

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

The built-in service container is meant to serve the needs of the framework and most consumer apps. We recommend using the built-in container unless you need a specific feature that it doesn't support. Some of the features supported in 3rd party containers not found in the built-in container:

换句话说,如果您需要 Autofac 的功能,您可以 still use AutofacIServiceCollection