C# 反应式扩展和IDisposable管理

C# 反应式扩展和IDisposable管理,c#,.net,.net-core,system.reactive,C#,.net,.net Core,System.reactive,我正在尝试使用Microsoft.Management.Infrastructure的Async版本,但我很难弄清楚如何使用反应式扩展进行会话管理 以下是一些背景: 可以使用创建CIM会话,它返回IObservable CimSession.CreateAsync返回一个 cimsynchdelegatedobservable,因此当不再需要时,必须手动处理CimSession 在获得CimSession的句柄后,我尝试运行WQL查询,例如使用session.queryInstanceAsyn

我正在尝试使用Microsoft.Management.Infrastructure的
Async
版本,但我很难弄清楚如何使用反应式扩展进行会话管理

以下是一些背景:

  • 可以使用创建CIM会话,它返回
    IObservable
  • CimSession.CreateAsync
    返回一个
  • cimsynchdelegatedobservable
    ,因此当不再需要时,必须手动处理
    CimSession
  • 在获得
    CimSession
    的句柄后,我尝试运行WQL查询,例如使用
    session.queryInstanceAsync(@“root\cimv2”、“WQL”、“从Win32\U ComputerSystem中选择用户名”)
如果
CimSession
返回的是
Task
s而不是
Observable
s,那么代码将非常简单:

使用var session=CimSession.CreateAsync(“.”);
var results=session.queryInstanceAsync(@“root\cimv2”、“WQL”、“从Win32_ComputerSystem中选择用户名”);
但是由于
Async
方法是使用
Observable
s实现的,我不知道如何将其转化为
Observable
s的惯用用法。当然,我可以使用
System.Reactive.Linq.Observable.ForEachAsync
将我的方法转换为
任务
,但我想学习如何正确使用Observable

总而言之,我的问题是:

  • CimSession
    的生存期绑定到
    可观察的
  • 如果没有订阅者,如何确保处置
    CimSession
    ?我应该强制至少一个订阅者,但使用工厂方法吗
  • queryInstanceAsync
    的结果到达时,如何处理
    CimSession
    可观察到的内容

这是一个有点古怪的界面,但试一试,让我知道它是否有效:

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;
IObservable查询=
来自CimSession.CreateAsync(“.”)中的会话
从可观察的x开始。使用(
()=>会议,
s=>s.QueryInstanceAsync(@“root\cimv2”、“WQL”、“从Win32\U计算机系统中选择用户名”))
从可观察的y开始。使用(
()=>x,
z=>Observable.Return(z.GetCimSessionComputerName())
选择y;

如果这样做有效,我建议将其包装在单独的类中:

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;
}
公共静态类CimSessionEx
{
公共静态IObservable CreateObservable(字符串computerName、字符串namespaceName、字符串queryDialect、字符串queryExpression、函数工厂)=>
从CimSession.CreateAsync(computerName)中的会话
使用(()=>session,s=>s.QueryInstanceAsync(namespaceName,queryDialect,queryExpression))
使用(()=>实例,工厂)
选择y;
}
然后你可以这样使用它:

IObservable<string> query =
    CimSessionEx.CreateObservable(
        ".",
        @"root\cimv2",
        "WQL",
        "SELECT Username FROM Win32_ComputerSystem",
        i => Observable.Return(i.GetCimSessionComputerName()));
IObservable查询=
CimSessionEx.CreateObservable(
".",
@“根目录\cimv2”,
“WQL”,
“从Win32\u计算机系统中选择用户名”,
i=>Observable.Return(i.GetCimSessionComputerName());