简体   繁体   English

反应式扩展和 IDisposable 管理

[英]Reactive Extensions and IDisposable management

I'm trying to use Async versions of Microsoft.Management.Infrastructure , but I'm having hard time figuring out how to do session management with Reactive Extensions.我正在尝试使用Microsoft.Management.Infrastructure Async版本,但我很难弄清楚如何使用 Reactive Extensions 进行会话管理。

Here's some background:这是一些背景:

If CimSession returned Task s instead of Observable s, the code would be pretty straightforward:如果CimSession返回Task而不是Observable ,代码将非常简单:

using var session = CimSession.CreateAsync(".");
var results = session.QueryInstancesAsync(@"root\cimv2", "WQL", "SELECT Username FROM Win32_ComputerSystem");

But as the Async methods are implemented using Observable s, I'm not sure how to translate this to idiomatic usage of Observable s.但是由于Async方法是使用Observable实现的,我不确定如何将其转换为Observable的惯用用法。 Sure I could translate my methods to Task s using System.Reactive.Linq.Observable.ForEachAsync , but I'd like to learn how to use Observables properly.当然我可以使用System.Reactive.Linq.Observable.ForEachAsync将我的方法转换为Task ,但我想学习如何正确使用 Observables。

To sum it up, my questions would be:总结一下,我的问题是:

  • Bind lifetime of a CimSession to ObservableCimSession生命周期绑定到Observable
  • How to make sure CimSession gets disposed, if there are no subscribers?如果没有订阅者,如何确保CimSession得到处理? Should I force at least one subscriber, but having factory method?我应该强制至少一个订阅者,但有工厂方法吗?
  • How to dispose CimSession observable when results for QueryInstancesAsync arrive?QueryInstancesAsync结果到达时,如何处理CimSession observable?

It's a bit of a whacky interface, but give this a go and let me know if it works:这是一个有点古怪的界面,但试一试,让我知道它是否有效:

IObservable<string> query =
    from session in CimSession.CreateAsync(".")
    from x in Observable.Using(
        () => session,
        s => s.QueryInstancesAsync(@"root\cimv2", "WQL", "SELECT Username FROM Win32_ComputerSystem"))
    from y in Observable.Using(
        () => x,
        z => Observable.Return(z.GetCimSessionComputerName()))
    select y;

If that works, I'd suggest wrapping it in a separate class:如果可行,我建议将其包装在一个单独的类中:

public static class CimSessionEx
{
    public static IObservable<T> CreateObservable<T>(string computerName, string namespaceName, string queryDialect, string queryExpression, Func<CimInstance, IObservable<T>> factory) =>
        from session in CimSession.CreateAsync(computerName)
        from instance in Observable.Using(() => session, s => s.QueryInstancesAsync(namespaceName, queryDialect, queryExpression))
        from y in Observable.Using(() => instance, factory)
        select y;
}

Then you could use it like this:然后你可以像这样使用它:

IObservable<string> query =
    CimSessionEx.CreateObservable(
        ".",
        @"root\cimv2",
        "WQL",
        "SELECT Username FROM Win32_ComputerSystem",
        i => Observable.Return(i.GetCimSessionComputerName()));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM