11

「実行可能な」もののためのミニフレームワークに取り組んでいます。(実験、テスト、タスクなどです)

// Something that "runs" (in some coordinated way) multiple "runnable" things.
interface IRunnableOf<T> where : IRunnable

// Provide base-class functionality for a "runner"
abstract class RunnerBase<T> : IRunnableOf<T>


class SequentialRunner<T> : RunnerBase<T>  // Same interface, different behavior.
class ConcurrentRunner<T> : RunnerBase<T>
// other types of runners.

class ConcurrentBlockRunner : SequentialRunner<Block>
class SequentialBlockRunner : ConcurrentRunner<Block>

さて、どうすれば と を調和させることができるConcurrentBlockRunnerでしょSequentialBlockRunnerうか? これにより、次のことを意味します。

  1. コレクションで使用するために、共通の祖先によってそれらを参照します。(IEnuerable<T>ここで T = ??)

  2. 追加の基本クラス機能を提供します。(たとえば、プロパティを追加します)。


型パラメーターを指定した別のインターフェイスを追加することで、#1 を修正しましたIA<T>

interface IBlockRunner : IRunnableOf<Block> { }

myConcurrentBlockRunnerと のSequentialBlockRunner定義を次のように変更しました。

class ConcurrentBlockRunner : SequentialRunner<Block>, IBlockRunner
class SequentialBlockRunner : ConcurrentRunner<Block>, IBlockRunner

ConcurrentBlockRunnerSequentialBlockRunnerの両方Blockが型パラメーターに使用されているため、これは正しい解決策のようです。しかし、私はそれについて「奇妙」に感じずにはいられません。まあ、そのインターフェイスを追加しただけだからです。


#2 では、 と にいくつかの共通データを追加しConcurrentBlockRunnerますSequentialBlockRunner。それらに適用されるいくつかのプロパティがありますが、RunnerBase<T>.

C# を使用していて、多重継承が役立つと感じたのはこれが初めてです。私ができるなら:

abstract class BlockRunnerBase {
   int Prop1 { get; set; }
   int Prop2 { get; set; }

class ConcurrentBlockRunner : SequentialRunner<Block>, BlockRunnerBase
class SequentialBlockRunner : ConcurrentRunner<Block>, BlockRunnerBase

次に、これらの追加のプロパティを BlockRunnerBase に追加するだけで、すべてが機能します。より良い方法はありますか?


私は、私が作業を開始した構成をすぐに検討するように勧められることを知っています。

class BlockRunner : IBlockRunner  {
   IBlockRunner _member;

   int Prop1 { get; set; }    // Wish I could put these in some base class
   int Prop2 { get; set; }       

   // Lots of proxy calls, and proxy events into _member
   void Method() { _member.Method(); }
   event SomeEvent
   {
      add { _member.SomeEvent += value; }
      remove { _member.SomeEvent -= value; }
   }
}

私が遭遇した問題(この質問を書くように私を駆り立てた)は、一度作成すると型の互換性が失われることでした。私の場合、 _member がイベントを発生させていたので、senderパラメーターは typeSequentialBlockRunnerでした。ただし、イベント ハンドラーはそれを type にキャストしようとしましたがBlockRunner、もちろん失敗しました。add/removeを使用してイベントをプロキシするのではなく、実際にそれらを処理し、独自のイベントを発生させるソリューションがあります。いくつかのプロパティを追加するだけでも大変な作業です...

4

2 に答える 2

2

継承よりも合成、FTW!

より明確にするには:

class SequentialRunner<T> : RunnerBase<T>

を継承せずに実装IRunnableOf<T>してプロキシする必要があります。RunnerBase<T>

class SequentialRunner<T> : IRunnableOf<T>
{
   private readonly RunnerBase<T> _runnerBase;

   ...
}
于 2012-06-12T00:31:57.283 に答える
1

プロパティのような要素であっても、拡張メソッドを使用してmixin のようなコンストラクトを作成できます。

C# のNRolesで特性のような構造を使用した実験も作成しました。

ただし、これらはすべて非標準のコーディングを必要とするため、サードパーティに公開することを意図した API には理想的ではありません。可能であれば、クラスを再配置し、インターフェースを使用して委譲で構成を使用するようにしてください。

于 2012-06-12T02:26:45.247 に答える