Win32 API(waveOut...
関数のファミリー)をラップするC#ライブラリを作成していますが、カプセル化を壊さずにコードのさまざまな部分間の相互作用を管理する方法がわからなくなっています。これまでのところ、次のような設定があります。
public class AudioDevice
{
...
private WaveOutSafeHandle hWaveOut;
...
}
// All native method calls happen in wrapper methods here, providing
// uniformity of access, exceptions on error MMRESULTs, etc.
static class NativeWrappers
{
...
internal static WaveOutSafeHandle OpenDevice(...) { ... waveOutOpen(...) ... }
...
}
// Native methods live in a class of their own, and are only called
// from NativeWrappers
static class NativeMethods
{
...
internal static extern MMResult waveOutOpen(...);
...
}
このコードで最も重要な点は、デバイスによってラップされたハンドルがデバイスの外部に表示されないことです。
AudioBlock
次に、ネイティブWAVEHDR
構造とオーディオサンプルデータをラップするクラスを追加します。私が直面している問題は、これから先、私が興味を持っている他のほとんどすべてのネイティブ関数(waveOut[Un]PrepareHeader
、waveOutWrite
)がハンドルと。の両方を必要とすることWAVEHDR
です。デバイスがに触れる必要があるWAVEHDR
か、ブロックがハンドルにアクセスできる必要があるようです。どちらのアプローチも、あるクラスが概念的にビジネスで知らない何かと相互作用することを意味します。
もちろん、これを回避する方法はいくつかあります。
ハンドルや
WAVEHDR
sをプライベートではなく内部にします。のネスト
AudioBlock
されたクラスを作成しDevice
ます。ブロックからヘッダーへのマッピングを(たとえば)維持する3番目のクラス(名前を考えることさえ躊躇します)があります
(foo)Manager
。これは、ブロックが与えられると、デバイスがブロックの内部に触れることなくサンプルを再生するのに役立ちます。
他にもあるかもしれません。私はそう願っています:)
これらのアプローチに対する私の異議(正しいか間違っているか):
厳密な意味では公開されていないかもしれませんが、内部メンバーを使用することは私には警官のように思えます。効果的に実装の詳細は、それらを必要としないライブラリの部分に引き続き表示されます。私は「このコードを使用または変更する人にどのインターフェースを提示したいのか」と考え続けています。
これはほとんど私の頭の中で機能します。ブロックをデバイスの「実装の詳細」と見なすことにより、デバイスの内部に依存できるようにすることがより受け入れられるように思われます。ブロックが実際には独立したエンティティであることを除いて。単一のデバイスに関連付けられておらず、デバイスのロジックの実装を支援するために使用されることもありません。
これは、私が維持したい分離のレベルに最も近くなりますが、私がよく行うように、過剰設計の領域に迷い始めています:Pまた、マッピングをそのまま維持するために、ブロックをどこかから中央に割り当てる必要があるという人工的な考えを紹介します。
それで、誰かがこのコードを(再)構築するための推奨事項を持っていますか?有効な答えには、私を説得できる限り、「あなたの異議#Xは蒸し暑い壷です」が含まれます:) ETA:たとえば、この種のことを強制しようとすることは、社会的手段(文書化、慣習)よりも優れていると思う場合技術的なもの(アクセス修飾子、アセンブリ境界)、私に知らせて、いくつかの参照を指摘してください。