2010-12-10 12 views
0

愚かなアイデアのように聞こえますが、どういうことかと思っていました。実行時に基底クラスを別の基底クラスに変更/スワップ

実行時に派生クラスの基本クラスを変更することはできますか?もちろん、多くのifとbutsがあり、誰かがそれをして、なぜその悪いデザインをしているのかという疑問があります。

完全に有効かもしれませんが、それらを脇に置いて、ちょうどキックやナーディネスを示すために、C#や他言語で可能でしょうか?

だから、のようなもの:これは、C#でことはできません

public class baseOriginal { 
    public string justAProperty; 
} 

public class baseSwapped { 
    public int sillyNumber; 
} 

public class derivedClass : baseOriginal { 
    public bool iAmDumb; 
} 

void Main() { 
    baseOriginal derived = new derivedClass(); 
    Console.WriteLine(derived.justAProperty); 
    baseSwapped derivedSwapped = (??); 
    Console.WriteLine(derivedSwapped.sillyNumber); 
} 
+1

これは自己修正コードです。 "私は哺乳類です!" "いいえ、私は爬虫類です!" "ああ、今私は鳥になりたい!" –

+1

継承を超える構成を検討する必要があります。 –

+0

現在のところ、このための実際のユースケースはありません。私は全く悪いデザインに同意します。私はこれを聞いた理由は私が誰かがそれについて話し、彼らが(多分C + +で)それをしたと主張したと聞いた。私は彼を華麗な男として高く評価していますが、彼を信じることはできませんでした。私はたくさんのことを試み、これを「不可能」とする前に、コミュニティの意見を求めました。 DLRの考え方は面白いようです。何かができるかどうかを見るために、週末にいくつかの掘削をするでしょう。 – Mrchief

答えて

0

私は考えることができる最も近いものは以下の通りです:

http://msdn.microsoft.com/en-us/library/dd264736.aspx

static void Main(string[] args) 
{ 
    ExampleClass ec = new ExampleClass(); 
    // The following line causes a compiler error if exampleMethod1 has only 
    // one parameter. 
    //ec.exampleMethod1(10, 4); 

    dynamic dynamic_ec = new ExampleClass(); 
    // The following line is not identified as an error by the 
    // compiler, but it causes a run-time exception. 
    dynamic_ec.exampleMethod1(10, 4); 

    // The following calls also do not cause compiler errors, whether 
    // appropriate methods exist or not. 
    dynamic_ec.someMethod("some argument", 7, null); 
    dynamic_ec.nonexistentMethod(); 
} 

class ExampleClass 
{ 
    public ExampleClass() { } 
    public ExampleClass(int v) { } 

    public void exampleMethod1(int i) { } 

    public void exampleMethod2(string str) { } 
} 

動的言語ランタイムは、あなたがそれをやりたいことができれば、私は考えています。あなたは になり得ることができる最も近い

はその後、インターフェイスとして少なくとも 1で他の1つに由来 キャストを定義することによって、両方のタイプから派生します。

私が同意しなければならないことは、この提案が彼がしたいことを満足させるという例に基づいて、彼が実際にやりたいことであるということです。

+0

DLRを再生しようとします。ありがとう。 – Mrchief

+0

これは答えに最も近いです... – Mrchief

1

。おそらくあなたが望むのは、JavaScriptのような動的言語でよく見られるプロトタイプベースのソリューションで、定義方法にオブジェクトの機能を「拡張」することができます。

しかし、コードのヒントを達成するには、交換可能なクラスに共通の祖先クラスを継承させることができます。そうすれば、それぞれのインスタンスをそれぞれの地位に割り当てることができます。あなたが得ることができる

public class baseClassAncestor{ 

} 
public class baseOriginal:baseClassAncestor { 
    public string justAProperty; 
} 

public class baseSwapped:baseClassAncestor { 
    public int sillyNumber; 
} 

public class derivedClass : baseOriginal { 
    public bool iAmDumb; 
} 
0

最寄のは、他に1由来の鋳造、インターフェイスとして少なくとも一つを定義することによって、両方のタイプから派生することです。

1

派生クラスを使用して基本クラスBEFOREを実装する異なるアセンブリをロードすることによって、1つのタイムベースクラススワップを実行できます。しかし、このアプローチではコンパイルできないため、正確なコードは動作しませんが、別の基底クラスのメソッドへのアクセスを別々の関数に移動することで動作させることができます。

すべての基本クラスから可能なすべてのメソッド/プロパティを含むUnionBaseクラスを追加して、このクラスのアセンブリに対してメインコードをコンパイルできます。実行時に、特定の基本クラスを含むアセンブリをロードするよりも、

通常の警告:このルートに行くための非常に良い理由と理解が必要です。私。既存の外部コードがそのようなアプローチを検討する理由です。

「自宅で行うのではなく、熟練した専門家による閉鎖コースで行う」。

1

もう一つの可能​​な回避策は、シームレスに既存の型に新しいメソッドとインターフェースを注入ならびに修正することができるコンパイル時weaving、即ちPostSharp、(インターセプト)既存のものに基づいており、いくつかのAOP溶液を用いて実施することができます。

+0

これは私の心を越えました。私は基本クラスを交換しようとしていませんが。 – Mrchief

1

実際には、基本クラスを入れ替えたい場合があります。たとえば、基本クラスを変更したいとしますが、現在のコードベースが他のチームと共有されているときに混乱させたくないとしましょう。たとえば、基底から継承する10以上の派生クラスがあるとしましょう。 10以上のカスタム派生クラスを作成して基本クラスをオーバーライドすることはできますが、それは多くの作業です。ここにあなたがしていることがあります。この問題の鍵は、インターフェイスとベースプロキシクラスを作成することです。

class Program 
{ 
    static void Main(string[] args) 
    { 
      IActionable action = new Derived<Base1>(); 
      action.open(); 
      action = new Derived<Base2>(); 
      action.open(); 

    } 
} 

// Proxybase is a fake base class. ProxyBase will point to a real base1 or 
// base2 
public class Derived<T>:ProxyBase,IActionable 
{ 
    public Derived():base(typeof(T))  

    // the open function is not overriden in this case allowing 
    // the base implementation to be used 
} 

// this looks like the real base class but it is a fake 
// The proxy simply points to the implementation of base1 or base2 instead 
public abstract class ProxyBase: IActionable 
{ 
    IActionable obj; 
    public ProxyBase(Type type,params object[] args) 
    { 
      obj = (IActionable)Activator.CreateInstance(type,args); 
    } 

    public virtual void open() 
    { 
      obj.open(); 
    } 
} 

// notice base1 and base2 are NOT abstract in this case 
// consider this the original implementation of the base class 
public class Base1: IActionable 
{ 
     public virtual void open() 
     { 
      Console.WriteLine("base1 open"); 
     } 

} 

// here base2 acquired the functionality of base1 and hides base1's open 
    function 
// consider this implementation the new one to replace the original one 
public class Base2: Base1, IActionable 
{ 
    public new virtual void open() 
    { 
      Console.WriteLine("base2 open"); 
    } 
} 

public interface IActionable 
{ 
    void open(); 
} 

base1 open 
base2 open 

UPDATE次のように結果は次のようになります。 をこの答えは動作しますが、現実には、継承が最高の状態でこの練習を困難にカップリングを導入していることです。また、実際のシナリオでは、あなたの要件によって、C#では不可能な複数の基本クラスから派生したいと思うかもしれません。基本クラスを交換したい場合は、ブリッジ設計パターンを使用することをお勧めします(実際に継承を回避し、カップリングを回避します)。

+0

これは、私が正当な意図を持って正当なものをやっていれば、私がやることです。私の質問はもともとそのような意図はなかった! :)私は、コンパイルされたコードの表現が、そのような黒い魔法のための別の実行可能な道であるかもしれないが、時間をつかまえていなかったことに気づいた。 – Mrchief

関連する問題