インターフェースで定義されているかのようにクラスを扱います
-
19-08-2019 - |
質問
類似した要素と独自の要素を持つ100個のクラスがあります。これらの類似項目に名前を付けるインターフェイスを作成しました。たとえば、インターフェイスIAnimalです。私が通常やることは:
class dog : IAnimal
しかし、100のクラスがあり、それらすべてを調べて、IAnimalを適用できるクラスを探したいとは思いません。
やりたいことはこれです:
dog scruffy = new dog();
cat ruffles = new cat();
IAnimal[] animals = new IAnimal[] {scruffy as IAnimal, ruffles as IAnimal} // gives null
または
IAnimal[] animals = new IAnimal[] {(IAnimal)scruffy, (IAnimal)ruffles} //throws exception
then do
foreach (IAnimal animal in animals)
{
animal.eat();
}
c#を作成する方法はありますか?
ありがとう!
EDIT(レイジーではありません):クラスはsql stored procメタデータから生成されます。つまり、生成されるたびに戻って追加するか、コードジェネレーターを変更してメンバーを特定する必要があります。インターフェイス、実際には悪い考えではありません。何らかのジェネリックアプローチか何かがあることを望んでいました。
解決
部分クラスでこの問題を解決できます。各クラスの1つのソースファイルにマシン生成/再生成コードを入れ、手作業でコーディングした部分(IAnimalからサブクラスを定義)を別。
他のヒント
あなたが求めているのはダックタイピングと呼ばれ、C#の一部ではありません。解決策には、リフレクションとプロパティの確認が含まれます。手作業でクラスをチェックする方が迅速だと思います。
しかし、試してみるのは興味深いプロジェクトです。
解決策は、コードジェネレーターを変更することです。現在、あなたのニーズには単純すぎます。関連するプロパティやメソッドがクラスに存在する場合、インターフェイス実装を追加する必要があります。
<!> quot; eat
<!> quot;にアクセスするアダプターを作成できます。リフレクションを介して、貧乏人のアヒルの入力:
public class Adapter<T> : IAnimal
{
private T x;
Adapter(T x)
{
this.x = x;
}
public void eat()
{
x.GetType().GetMethod("eat").Invoke(this);
}
}
その後、次のように使用できます:
dog scruffy = new dog();
cat ruffles = new cat();
IAnimal[] animals = new IAnimal[] {new Adapter<dog>(scruffy), new Adapter<cat>(ruffles )};
私が知っていることは簡単ではありませんが、リフレクションを使用して遅延バインディング呼び出しを行うことはできますが、クラスを編集するか、マクロを作成して時間を費やす方が良いでしょう
正当な理由でcatクラスを本当に変更できないと仮定すると、
IAnimalから継承したcat用のアダプターを作成できます。例:
class cat_adapter : IAnimal
{
private cat baseCat;
public cat_adapter( cat aCat)
{
baseCat = aCat;
}
// Implement IAnimal interface and redirect to baseCat
public void eat()
{
baseCat.munchOnMeowMix();
}
}
C ++では、生成されたすべてのクラスに同じ関数が必要であると仮定して、テンプレートを使用できます。
template <class BaseType>
class CAnimalAdapter : public IAnimal
{
private:
BaseType* m_baseInstance;
public:
CAnimalAdapter(BaseType* baseInstance) :
m_baseInstance(baseInstance)
{
}
void eat()
{
// You will get a compiler error if BaseType doesn't have this implemented
baseInstance->doEat();
}
}
おそらく、私よりもC#-pyの方がリフレクションで同じことができるでしょう。
コードジェネレーターがクラスをパーシャルとして生成する場合、インターフェイスを実装する別のパーシャル定義を追加できます。
いいえ。具体的な基本クラスまたはインターフェイスを持たずに、C#でこれを実行する方法はありません。
クラスは、インターフェイスIAnimalを実装する必要があります。 2つの異なるクラスの同じ名前のメソッド/プロパティは、両方がインターフェイス/ベースクラスの実装でない限り、同等とは見なされません。
すでにメソッドを実装しており、インターフェイスを実装するだけの場合は、IDEでファイル内の置換コマンドで正規表現を使用できます。
それ以外の場合は、拡張メソッドを見てください。彼らはあなたのニーズに合うかもしれません。
生成されたクラスを部分クラスとして実装する場合、これらのクラスにインターフェイスを実装してから、部分クラスの半分のみを生成するようにコードジェネレーターを変更できます。これにより、インターフェイス実装(または追加することを決定した他のカスタムロジック)を失うことなく、クラスを再生成できます。
このタイプのアプローチは、LINQ to SQLがクラスファイルを生成する方法です。