2013-03-18 5 views
7

他のクラスに含まれるメソッドからクラスを動的に作成できますか?Cでクラスを動的に作成する

たとえば、クラスA、B、Cには、簡単に識別できる名前のパブリックメソッドがあります。それらを抽出してクラスDに追加する必要があります。次に、実装ロジックのすべてを含むクラスDは、クラスDの単一インスタンスのみを受け入れ、これらのメソッドを他の関数に動的にバインドするシステムにさらに渡すことができます。

明らかに、これは私が探している継承ではありません。私は文字通り、別の名前のメソッドが1つのクラスに詰め込まれる必要があることを述べています。これらの命名規則を理解し、動的にバインドするシステム(それは私にとってはブラックボックスです)。

私はA、B、Cからメソッドを抽出し、それらをメモリ内のクラスDのソースと動的に結合し、それらを新しいクラスDにコンパイルし、Dのインスタンスを作成して渡すそれは前方にある。

public class A{ public void EXPORT_A_DoSomething(){} } 
public class B{ public void EXPORT_B_DoSomethingElse(){}} 
public class C{ public void EXPORT_C_DoAnything(){}} 
//should become 
public class D{ 
      public void EXPORT_A_DoSomething(){} 
      public void EXPORT_B_DoSomethingElse(){} 
      public void EXPORT_C_DoAnything(){} 
} 

クラスA、BおよびCからMethodInfosを抽出し、何らかの形で直接クラスDにそれらをアタッチする方法はありますか?もしそうなら、どのように?

+3

クラスのコードをプレーンテキストファイルに出力して保存し、実行時にコンパイルすることができます。これを行う方法については、[CSharpCodeProvider Class](http://msdn.microsoft.com/en-us/library/microsoft.csharp.csharpcodeprovider.aspx)と関連トピックを参照してください。 –

+1

私が知る限り、メソッドの実装をコピーする方法はありません。おそらく私は、A、B、Cのインスタンスを含むDynamicObject派生クラスを作成し、これらの名前を持つDynamicObject派生クラスのimlpementメソッドを作成し、単にそれらを包含オブジェクトにプロキシするだけです。それは私があなたが何を求めているのかを理解していると仮定します。私はこれがうまくいくと思います。 – Pete

+1

@ JohnWillemse:メソッドが同じシグネチャを共有する場合は、マルチキャストの代理人が役に立ちます。 – TalentTuner

答えて

2

私はC# Class compilerの使用を検討します。私が覚えていることは、文字列のコードを作成し、アセンブリを出力として取得できることです。これにより、リフレクションを通じてメソッドを呼び出すことができます。

私が指定したMSDNリンクには例がありますが、私は自分のプロジェクトを見つけたらここで黙っています。

+0

私はクラスA/B/Cのソースにアクセスできるので、動的コンパイルは最も直接的な「ブルートフォース」アプローチのようです。以下のコメント欄には、これらのクラス内のプライベートデータを統合する複雑さがありました。 –

-1

他のクラスのメソッドを指し示すDクラスの代理人のハッシュまたはリストを使用して単純に考えましたか?代わりに、動的オブジェクト(google ExpandoObject)を使用してください。

+0

残念なことに、メソッドはそれらを使用するシステムによるリフレクションを介してアクセス可能でなければならないので、これは機能しません。 –

+0

少しでも余計な作業をしても、ダイナミックオブジェクトを引き続き反映させることができます。私は代議員を使って書き留めません。 – pfries

0

別の解決策は、クラスを取得し、インターフェースとしての機能のためのアクセサを設定し、興味のある関数を宣言定義することです。だから、

interface iA 
{ 
    public int a { get; set; } 
} 
interface iB 
{ 
    public int b { get; set; } 
} 
interface iAB : iA, iB 
{ 
} 
class MyClass : iA, iB 
{ 
    public int b { get; set; } 
    public int a { get; set; } 
} 
static class MyClassExtender 
{ 
    static public int Foo(this iAB ab) 
    { 
     int c = ab.a + ab.b; 
     ab.a = c; 
     return c; 
    } 
    static public int FooA(this iA a) 
    { 
     int c = ab.a + 1; 
     ab.a = c; 
     return c; 
    } 
    static public int FooB(this iB b) 
    { 
     int c = ab.b + 1; 
     ab.a = c; 
     return c; 
    } 

} 

今「MyClassの」フー、FooAを、使用することができますし、パブリックメソッドとしてFooB。

+0

残念ながら、メソッドを静的にすることはできません。私は拡張メソッドが大好きですが、この特定のケースでは動作しません。メソッドはパブリックインスタンスメンバである必要があります。 –

+0

好奇心の外に、これらが機能しないようにする機能は何ですか?上記の方法を使用して副作用を引き起こすことができ、内部インターフェースを使用してモジュールから項目を隠すことができます。それは、インターフェイスの巨大な広がりを作成するので、私はどのように設計パターンが維持できるか分からない。 – IdeaHat

0

"Mixins"とプロキシジェネレータを使用して実際には可能です。 Castle.DynamicProxyのチュートリアルをご覧ください:Mixins

1

メソッドだけをエクスポートすることはできません。これらのメソッドは、実際に存在するクラスから分離することはできません(継承されたメンバーフィールドやプロパティのすべてにアクセスする必要があります)。

私はあなたができる唯一のことは、インターフェイスの実装を出すことだと思います。 (あなたが必要とするものではないと言っていても、私はそれらのオブジェクトのプライベート状態を必要としない方法はありません)

必要なメソッドだけを含む1つのインターフェイスを作成し、オブジェクトの各タイプのインスタンスを含むオブジェクトをサポートします。

public class A{ public void DoSomething(){} } 
public class B{ public void DoSomethingElse(){}} 
public class C{ public void DoAnything(){}} 

public interface ID 
{ 
    void A_DoSomething(); 
    void B_DoSomethingElse(); 
    void C_DoAnything(); 
} 

public class D : ID 
{ 
    private A a; 
    private B b; 
    private C c; 

    public D(A a,B b, C c) { this.a=a;this.b=b;this.c=c; } 

    public void A_DoSomething(){ a.DoSomething();} 
    public void B_DoSomethingElse(){ b.DoSomethingElse();} 
    public void C_DoAnything(){ c.DoSomething(); 
} 

これを動的に生成する必要がある場合は、Reflection.Emitを調べます。新しいアセンブリを作成してAppDomainに動的にロードする方法については、いくつかのビジネスがあります。私はあなたができるならそれを避けようとします。

+0

私たちは潜在的に何百ものメソッドを動的に行う必要があると言っていますが、これを解決策として見ることができます。私は、他の開発者が必要とした各メソッドのインタフェースIDを維持する、人間の繁栄したバージョンを見ることができます。私はあなたが提案したコードの "パススルー"性が好きです。私が持っていたアイデアの1つはハイブリッドでした。クラスA、B、Cなどへの呼び出しであるスタブをクラスDに動的に書き出します。私は、インターフェースを使用することで、コード化されたメソッドの実装を直接行うことができます。 –

+0

t4テンプレートを使ってこのようなものを生成することができます。 「実行時に読み込まれる」のように動的ではありませんが、多くの配管コードを書く負担が軽減されます。 –

関連する問題