Managed Extensibility Framework(MEF)入門 -Export-

2MEFではパーツのパーツ自信のインスタンス、プロパティ(フィールド)、メソッドをコンテナーに対しサービスと言う形でエクスポートする事が出来ます。

 

export_details

 

コンテナーにパーツ単位で登録するのが一般的です。サンプルコードを元に見ていきましょう。

 

クラスインスタンスのエクスポート

クラスインスタンスをサービスとしてエクスポートするサンプルです。

C#
    1 using System;
    2 using System.ComponentModel.Composition;
    3 using System.ComponentModel.Composition.Hosting;
    4 
    5 namespace ExportClass.CSharp
    6 {
    7    public class Program
    8    {
    9       /// <summary>
   10       /// コンテナー
   11       /// </summary>
   12       private CompositionContainer container;
   13 
   14       private Program()
   15       {
   16          //コンテナーを生成
   17          this.container = new CompositionContainer();
   18          container.ComposeParts(this);
   19          //パーツ管理クラス
   20          CompositionBatch batch = new CompositionBatch();
   21          //MessageSenderをパーツとして登録
   22          batch.AddPart(new MessageSender());
   23          //パーツ管理クラスを元にコンテナーを構成
   24          this.container.Compose(batch);
   25       }
   26 
   27       private void Run()
   28       {
   29          //コンテナーよりエクスポートしたサービスを取得する。
   30          MessageSender messageSender = this.container.GetExportedValue<MessageSender>();
   31          Console.WriteLine(messageSender.GetMessage());
   32       }
   33 
   34       public static void Main(string[] args)
   35       {
   36          Program program = new Program();
   37          program.Run();
   38       }
   39    }
   40 
   41    //クラスインスタンスとしてエクスポート
   42    [Export]
   43    public class MessageSender
   44    {
   45       public string GetMessage()
   46       {
   47          return "メッセージです。";
   48       }
   49    }
   50 }
VB
    1 Imports System
    2 Imports System.ComponentModel.Composition
    3 Imports System.ComponentModel.Composition.Hosting
    4 
    5 Public Class Program
    6    ''' <summary>
    7    ''' コンテナー
    8    ''' </summary>
    9    Private container As CompositionContainer
   10 
   11    Private Sub New()
   12       'コンテナーを生成
   13       Me.container = New CompositionContainer()
   14       'パーツ管理クラスを生成
   15       Dim batch As New CompositionBatch()
   16       'MessageSenderをパーツとして登録
   17       batch.AddPart(New MessageSender())
   18       'パーツ管理クラスを元にコンテナーを構成
   19       Me.container.Compose(batch)
   20    End Sub
   21 
   22    Private Sub Run()
   23       'コンテナーよりエクスポートしたサービスを取得する。
   24       Dim messageSender As MessageSender = Me.container.GetExportedValue(Of MessageSender)()
   25       Console.WriteLine(messageSender.GetMessage())
   26    End Sub
   27 
   28    Public Shared Sub Main()
   29       Dim program As New Program()
   30       program.Run()
   31    End Sub
   32 End Class
   33 
   34 'クラスインスタンスとしてエクスポート
   35 <Export()> _
   36 Public Class MessageSender
   37    Public Function GetMessage()
   38       Return "メッセージです。"
   39    End Function
   40 End Class

上記はMessageSenderクラスをクラスインスタンスとしてコンテナーにエクスポートしている例です。クラスインスタンスをコンテナーにエクスポートするようにマーキングするには、クラスに属性として『System.ComponentModel.Composition.ExportAttribute』を定義します。サンプルコードではC#(16行目〜23行目)とVB(12行目〜19行目)でコンテナーにMessageSenderインスタンスをサービスとして、MessageSenderクラスをパーツとして登録しています。CompositionContainerクラスやCompositionBatchクラスが登場しておりますが、今後詳細を取り上げますのでそれまではエクスポートする定型文として今は覚えておいて下さい。登録後のサービスをC#(29行目)とVB(24行目)で取得し使用しています。サンプルコードではMessageSenderクラスのインスタンスを明示的に生成しており、冗長なファクトリークラスを定義しているようにしかなっておりません。DIコンテナーのメリットの「インターフェースと実装の分離」が行われておりませんので、MessageSenderクラスを実装クラスとし、新たにIMessageSenderインターフェースを作成したサンプルを見てみましょう。

C#
    1 using System;
    2 using System.ComponentModel.Composition;
    3 using System.ComponentModel.Composition.Hosting;
    4 
    5 namespace ExportClass.CSharp
    6 {
    7    public class Program
    8    {
    9       /// <summary>
   10       /// コンテナー
   11       /// </summary>
   12       private CompositionContainer container;
   13 
   14       private Program()
   15       {
   16          //コンテナーを生成
   17          this.container = new CompositionContainer();
   18          container.ComposeParts(this);
   19          //パーツ管理クラス
   20          CompositionBatch batch = new CompositionBatch();
   21          //MessageSenderをパーツとして登録
   22          batch.AddPart(new MessageSender());
   23          //パーツ管理クラスを元にコンテナーを構成
   24          this.container.Compose(batch);
   25       }
   26 
   27       private void Run()
   28       {
   29          //コンテナーよりエクスポートしたサービスを取得する。
   30          IMessageSender messageSender = this.container.GetExportedValue<IMessageSender>();
   31          Console.WriteLine(messageSender.GetMessage());
   32       }
   33 
   34       public static void Main(string[] args)
   35       {
   36          Program program = new Program();
   37          program.Run();
   38       }
   39    }
   40 
   41    public interface IMessageSender
   42    {
   43       string GetMessage();
   44    }
   45 
   46    //IMessageSender型としてエクスポート
   47    [Export(typeof(IMessageSender))]
   48    public class MessageSender : IMessageSender
   49    {
   50       public string GetMessage()
   51       {
   52          return "メッセージです。";
   53       }
   54    }
   55 }
VB
    1 Imports System
    2 Imports System.ComponentModel.Composition
    3 Imports System.ComponentModel.Composition.Hosting
    4 
    5 Public Class Program
    6    ''' <summary>
    7    ''' コンテナー
    8    ''' </summary>
    9    Private container As CompositionContainer
   10 
   11    Private Sub New()
   12       'コン テナーを生成
   13       Me.container = New CompositionContainer()
   14       'パーツ管理クラスを生成
   15       Dim batch As New CompositionBatch()
   16       'MessageSenderdをパーツとして登録
   17       batch.AddPart(New MessageSender())
   18       'パーツ管理クラスを元にコンテナーを構成
   19       Me.container.Compose(batch)
   20    End Sub
   21 
   22    Private Sub Run()
   23       'コンテナーよりエクスポートしたサービスを取得する。
   24       Dim messageSender As IMessageSender = Me.container.GetExportedValue(Of IMessageSender)()
   25       Console.WriteLine(messageSender.GetMessage())
   26    End Sub
   27 
   28    Public Shared Sub Main()
   29       Dim program As New Program()
   30       program.Run()
   31    End Sub
   32 End Class
   33 
   34 Public Interface IMessageSender
   35    Function GetMessage() As String
   36 End Interface
   37 
   38 'IMessageSender型としてエクスポート
   39 <Export(GetType(IMessageSender))> _
   40 Public Class MessageSender
   41    Implements IMessageSender
   42    Public Function GetMessage() As String Implements IMessageSender.GetMessage
   43       Return "メッセージです。"
   44    End Function
   45 End Class

 

このようにインターフェース型への実装の注入が簡単に行える事が分かります。現在はコンテナーより直接エクスポートしたサービスを取得していますが、次回取り上げる「インポート」と併用する事で利便性が格段に向上します。

 

Source code