2012-05-07 35 views
1

実行時にクラスにインターフェイス実装を追加する方法を探しています。 サンプルコードは次のとおりです。クラスにインターフェイスをプログラムで(実行時に)追加する方法

Public Interface IAction 
    Sub DoThis(a As Integer) 
End Interface 


Class Actor 
Implements IAction 

    Private mNumber As Integer 

    Public Sub New(number As Integer) 
     mNumber = number 
    End Sub 

    Public Sub DoThis(a As Integer) Implements IAction.DoThis 
     Console.WriteLine(String.Format("Actor #{0}: {1}", mNumber, a)) 
    End Sub 

End Class 


Class ActionDispatcher 
Implements IAction 

    Private Shared mActionList As New List(Of IAction) 

    Public Shared Sub Add(actor As IAction) 
     mActionList.Add(actor) 
    End Sub 

    Public Sub DoThis(a As Integer) Implements IAction.DoThis 
     For Each act In mActionList 
      act.DoThis(a) 
     Next 
    End Sub 

End Class 


Module Module1 

    Sub Main() 
     Dim a As New ActionDispatcher 
     ActionDispatcher.Add(New Actor(1)) 
     ActionDispatcher.Add(New Actor(2)) 
     a.DoThis(5) 
    End Sub 

End Module 

これは、1つのエンドポイントのために必要なすべてのインタフェースを実装する単一のクラスを、CreateHostするために提供する必要がWCF、に関連しています。このシナリオでは、ActionDispatcherはそのようなクラスであり、IActionは実装する多くのインターフェイスの1つです。

私はActionDispatcherを手動で実装することを避けたいと思いますが、ActionDispatcherがIAction、IDoing、INoActionなどのインターフェイスを実装し、ディスパッチメソッドを生成する必要がある登録メカニズムがあります。

MSDNによると、どのクラスもどのインターフェイスとも互換性があるため、ActionDispatcherで "Implements"を宣言する必要はありません。しかし、私はまだインターフェイスを実装して実装メソッドをインターフェイス定義に接続する必要があるので、WCFは必要なときにそれを見つけることができます。

私が見つけた最も近いものはおそらくAutomatic Interface Implementerですが、(1)は新しいタイプを作成し、(2)はダミーメソッドを追加します。

私はCodeCompileUnitクラスについても理解しようとしましたが、これまでのところ私が必要とするものとの関係を見ることができませんでした。

Reflection APIでもっと経験豊かな人が助けてくれますか?私が望んでいるwhayをする良い方法はありますか?

+0

私はこの練習の途中です。おそらく、私が今思うほとんどのものはIL(アセンブラほど自明ではありませんが、エラーが発生しやすい)ですが、文字列からILコードを生成することです: Compiler.CompileToIL("Public Sub DoThat(a As Integer) Implements ... End Sub") MikNik

答えて

2

私はついにそれを強く打ちました。 intricationsに興味のある人のために、(短い中)溶液である:

Class ActionDispatcher

Private Shared mImplementorType As Type 

Public Shared Function GetImplementorType() As Type 
    If mImplementorType Is Nothing 
     mImplementorType = CreateImplementorType() 
    End If 

    Return mImplementorType 
End Function 

Private Shared Function CreateImplementorType() As Type 
    ' Nice to have RunAndSave for debugging with ILdasm/ILSpy 
    Dim myAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
     New AssemblyName() With { .Name = "ViewerDispatcherAssembly" }, 
     AssemblyBuilderAccess.RunAndSave) 
    Dim mbuilder = myAssemblyBuilder.DefineDynamicModule("ViewerDispatcherModule", "ViewerDispatcherModule.dll") 
    Dim tbuilder = mbuilder.DefineType("ViewerDispatcherImpl", TypeAttributes.Class Or TypeAttributes.Public) 

    For Each itype In mInterfaceTypes 
     tbuilder.AddInterfaceImplementation(itype) 
     For Each method In itype.GetMethods() 
      ' Create interface implementation for each interface method. 
      CreateInterfaceImplementation(tbuilder, itype, method, capability, mbuilder) 
     Next 
    Next 
    Return tbuilder.CreateType() 
End Sub 

End Class

機能CreateInterfaceImplementation動的インターフェイスパラメータと正しいIAction関数を呼び出すために、このタイプのメソッドを保持する型を作成します。 tbuilderIActionの実装を作成します。 生成されたコードの量を最小限に抑えるために、mActionListをループする中間関数もあります。

0

まず、これは数行のコードを回避しようとしているようです。クラスにインターフェイスを実装する場合は、それを指定するだけで、.Netタイプのシステムの仕組みがわかります。

実際、あなたが本当に望むことをすることはできません。実行時にクラスのコードを変更することはできません。あなたが望むことができる最高のものは、インターフェイスを実装する新しいタイプを作成することです。しかし、ランタイムに新しいタイプを作成したくない場合(なぜですか?)、あなたは運が悪いと思います。

+0

私はもう少しそれを調べた。あなたは正しいです、実行時に新しい型を作成することが私の唯一の方法です。 なぜですか?まあ、私は自動化が好きです:-)新しいインターフェースを追加することはできるだけ無痛でなければならないので、可能な限りすべてのものを切り離してください。 – MikNik

+0

しかし、インターフェイスをクラスから切り離すのはあまり意味がありません。クラスを書くときには、実装するインターフェイス、実装するメンバ(とその方法)を知る必要があります。したがって、インターフェイスを明示的に指定することもできます。 – svick

+0

どうしてですか?実装するインタフェースが50個ある場合は、重複したコードをたくさん作成する必要はありません。実装するインターフェイスのリストを提供していれば、それは仕事です - これはより堅牢です。 – MikNik

0

リフレクションを使用してプロパティ値を記述していますが、実行時に既存の型に新しいプロパティとメソッドを注入することについて聞いたことがありますか?私にはあまりにも未来的なように聞こえる。

可能であれば、インターフェイスは、のいずれかのプロパティおよび/またはメソッドを定義するために使用され、常にが実装されています。実際に実装を自由に追加または削除することができれば、クラスに依存する他の型をいずれかの方法で破る可能性が非常に高いでしょう。