C# 包装可能是暂时对象的惯用方法

C# 包装可能是暂时对象的惯用方法,c#,C#,我正在为控制pulseaudio sound服务器的C库编写一些C#绑定,我不确定如何惯用地绑定一些暴露的潜在瞬态对象:特别是接收器 pulseaudio有一个音频接收器的概念,即播放给定音频流的硬件。这自然会映射到一个Sink类,该类具有一些明显的属性—体积等。问题是热插拔-音频硬件在运行时可能会来来往往,因此这样的Sink对象可能最终成为僵尸,指向不存在的硬件,并且对它们执行的所有操作都将失败。更糟糕的是,C库没有为接收器提供唯一的句柄,因此一系列热插拔事件可能会在代码没有注意到的情况下更改

我正在为控制pulseaudio sound服务器的C库编写一些C#绑定,我不确定如何惯用地绑定一些暴露的潜在瞬态对象:特别是接收器

pulseaudio有一个音频接收器的概念,即播放给定音频流的硬件。这自然会映射到一个
Sink
类,该类具有一些明显的属性—体积等。问题是热插拔-音频硬件在运行时可能会来来往往,因此这样的
Sink
对象可能最终成为僵尸,指向不存在的硬件,并且对它们执行的所有操作都将失败。更糟糕的是,C库没有为接收器提供唯一的句柄,因此一系列热插拔事件可能会在代码没有注意到的情况下更改给定
Sink
实例实际控制的硬件

这两个问题都很棘手。我想提供一些
Sink
抽象,但我不确定如何避免这些问题

其他处于类似情况的人是如何处理此类问题的

编辑:在C库中,您似乎只希望在查询接收器和尝试更改其属性之间不会发生热插拔事件。汇在API中由索引标识,但这并不稳定。每个接收器也有一个标识符字符串,我认为它是唯一的,至少在每次运行时是唯一的


有一个API可以获取对各种有趣事件的回调,例如热插拔,因此可以将每个
接收器连接到该事件,并至少在它消失时得到通知。

难道您不能只侦听热插拔事件,然后使用您的库将其发送到应用程序吗?正常的C#模式是为Sink类实现INotifyPropertyChanged。

如果PulseAudio没有通知您硬件事件,那么处理这种情况基本上是站不住脚的。您需要为PA的C库编写一些补丁来优雅地处理此问题,尽管我很惊讶PA没有公开任何处理热插拔设备的方法。

我认为您应该尝试将C库的这种行为传达给C库的用户

我不熟悉pulseaudio,但根据您提供的关于唯一标识符的信息,
Sink
类的可能设计如下所示:

/// <summary>
/// Represents a sink. May refer to different hardware.
/// </summary>
public class Sink
{
    public static IEnumerable<string> GetCurrentIdentifiers() { ... }

    public static Sink GetSinkForIdentifier(string identifier) { ... }

    private Sink() { ... }
}
//
///表示水槽。可能指不同的硬件。
/// 
公共级水槽
{
公共静态IEnumerable GetCurrentIdentifiers(){…}
公共静态接收器GetSinkForIdentifier(字符串标识符){…}
专用接收器(){…}
}

有趣的阅读:


因此,我的建议不是尝试创建(泄漏的)抽象,而是简单地公开pulseaudio的概念。

c如何处理这种情况?每次你需要水槽时,你都会简单地重新询问它吗?听起来这是一个非常棘手的问题。我只能(脑子里)想着投票。绝对不是一个优雅的解决方案。我在原来的帖子中添加了一些额外的信息。PA提供了各种回调,包括热插拔事件。这至少可以解决第二个问题(以一点开销为代价),但仍然给我留下了一个僵尸水槽。库的使用者最终只会得到一个所有操作都失败的接收器对象,这看起来很难看;尝试对水槽进行更高的抽象,但也要暴露底层的PulseAudio概念以捕捉滴水。