在 .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 Autofac 和 IServiceCollection
。
我想使用 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 Autofac 和 IServiceCollection
。