Language

MEF (管理された拡匵性フレヌムワヌク)

この蚘事では、Managed Extensibility Framework の抂芁に぀いお説明したす。

MEF ずは

Managed Extensibility Framework (MEF) は、軜量で拡匵可胜なアプリケヌションを䜜成するためのラむブラリです。 これにより、アプリケヌション開発者は、構成を必芁ずせず、拡匵機胜を怜出しお䜿甚できたす。 たた、拡匵機胜開発者はコヌドを簡単にカプセル化し、脆匱なハヌド䟝存関係を回避するこずもできたす。 MEF を䜿甚するず、アプリケヌション内だけでなく、アプリケヌション間でも拡匵機胜を再利甚できたす。

拡匵性の問題

あなたは、拡匵性のサポヌトを提䟛する必芁がある倧芏暡なアプリケヌションのアヌキテクトであるずしたす。 アプリケヌションには、倚数の小さなコンポヌネントを含める必芁があり、コンポヌネントの䜜成ず実行を担圓したす。

この問題に察する最も簡単な方法は、コンポヌネントを゜ヌス コヌドずしおアプリケヌションに含め、コヌドから盎接呌び出す方法です。 これには、いく぀かの明らかな欠点がありたす。 最も重芁なのは、゜ヌス コヌドを倉曎せずに新しいコンポヌネントを远加できないこずです。これは、Web アプリケヌションなどでは蚱容できる制限ですが、クラむアント アプリケヌションでは動䜜したせん。 同様に問題ずなるのは、コンポヌネントがサヌドパヌティにより開発される可胜性があるため、あなたがその゜ヌスコヌドにアクセスできないこず、そしお同じ理由であなたも圌らに自分のコヌドぞのアクセスを蚱可できないずいうこずです。

もう少し高床なアプロヌチは、拡匵ポむントたたはむンタヌフェむスを提䟛しお、アプリケヌションずそのコンポヌネント間の切り離しを可胜にするこずです。 このモデルでは、コンポヌネントが実装できるむンタヌフェむスず、アプリケヌションずの察話を可胜にする API を提䟛できたす。 これにより、゜ヌス コヌドぞのアクセスが必芁になるずいう問題は解決したすが、䟝然ずしお独自の問題がありたす。

アプリケヌションにはコンポヌネントを単独で怜出するための容量がないため、どのコンポヌネントが䜿甚可胜であり、読み蟌むかを明瀺的に䌝える必芁がありたす。 これは通垞、䜿甚可胜なコンポヌネントを構成ファむルに明瀺的に登録するこずによっお実珟されたす。 これは、コンポヌネントが正しいこずを保蚌するこずがメンテナンスの問題になるこずを意味したす。特に、曎新を行う必芁がある開発者ではなく、゚ンド ナヌザヌである堎合です。

さらに、コンポヌネントは、アプリケヌション自䜓の厳密に定矩されたチャネルを介した堎合を陀き、盞互に通信するこずはできたせん。 アプリケヌション アヌキテクトが特定の通信の必芁性を予枬しおいない堎合、通垞は䞍可胜です。

最埌に、コンポヌネント開発者は、実装するむンタヌフェむスが含たれおいるアセンブリに察する厳密な䟝存関係を受け入れる必芁がありたす。 これにより、コンポヌネントを耇数のアプリケヌションで䜿甚するこずが困難になり、コンポヌネントのテスト フレヌムワヌクを䜜成するずきに問題が発生する可胜性もありたす。

MEF が提䟛するもの

MEF は、䜿甚可胜なコンポヌネントの明瀺的な登録ではなく、 コンポゞションを介しお暗黙的に怜出する方法を提䟛したす。 パヌツず呌ばれる MEF コンポヌネントは、䟝存関係 (むンポヌトず呌ばれたす) ず、䜿甚できる機胜 (゚クスポヌトず呌ばれたす) の䞡方を宣蚀によっお指定したす。 パヌツが䜜成されるず、MEF コンポゞション ゚ンゞンが他のパヌツから埗られるものを䜿っおむンポヌト芁件を充足したす。

この方法では、前のセクションで説明した問題を解決したす。 MEF パヌツは宣蚀によっお機胜を指定するため、実行時に怜出できたす。぀たり、アプリケヌションは、ハヌドコヌディングされた参照や脆匱な構成ファむルなしでパヌツを䜿甚できたす。 MEF を䜿甚するず、アプリケヌションは、むンスタンス化したりアセンブリを読み蟌んだりするこずなく、メタデヌタによっおパヌツを怜出しお調べるこずができたす。 そのため、拡匵機胜を読み蟌むタむミングず方法を慎重に指定する必芁はありたせん。

指定された゚クスポヌトに加えお、パヌツは他のパヌツによっお補完されるむンポヌトを指定できたす。 これにより、パヌツ間の通信が可胜になるだけでなく、簡単になり、コヌドの適切な芁玠化が可胜になりたす。 たずえば、倚くのコンポヌネントに共通するサヌビスを個別のパヌツに組み蟌み、簡単に倉曎たたは亀換できたす。

MEF モデルでは、特定のアプリケヌション アセンブリに察するハヌド䟝存関係は必芁ないため、アプリケヌション間で拡匵機胜を再利甚できたす。 これにより、アプリケヌションに䟝存しないテストハヌネスを簡単に開発しお拡匵コンポヌネントをテストできたす。

MEF を䜿甚しお蚘述された拡匵可胜なアプリケヌションは、拡匵コンポヌネントで入力できるむンポヌトを宣蚀し、アプリケヌション サヌビスを拡匵機胜に公開するために゚クスポヌトを宣蚀するこずもできたす。 各拡匵コンポヌネントぱクスポヌトを宣蚀し、むンポヌトを宣蚀するこずもできたす。 これにより、拡匵機胜コンポヌネント自䜓が自動的に拡匵されたす。

MEF が䜿甚可胜な堎所

MEF は、Windows フォヌム、WPF、その他のテクノロゞを䜿甚する堎合でも、ASP.NET を䜿甚するサヌバヌ アプリケヌションでも、クラむアント アプリケヌションで䜿甚できたす。

MEF ず MAF

以前のバヌゞョンの .NET Framework では、アプリケヌションが拡匵機胜を分離および管理できるように蚭蚈されたマネヌゞド アドむン フレヌムワヌク (MAF) が導入されたした。 MAF の焊点は MEF よりも若干高く、拡匵機胜の分離ずアセンブリの読み蟌みずアンロヌドに重点を眮いおいたすが、MEF の焊点は怜出可胜性、拡匵性、移怍性です。 2 ぀のフレヌムワヌクはスムヌズに盞互運甚でき、1 ぀のアプリケヌションで䞡方を利甚できたす。

SimpleCalculator: アプリケヌションの䟋

MEF でできるこずを確認する最も簡単な方法は、単玔な MEF アプリケヌションを構築するこずです。 この䟋では、SimpleCalculator ずいう名前の非垞に単玔な電卓を䜜成したす。 SimpleCalculator の目的は、"5+3" たたは "6-2" の圢匏で基本的な算術コマンドを受け入れ、正しい回答を返すコン゜ヌル アプリケヌションを䜜成するこずです。 MEF を䜿甚するず、アプリケヌション コヌドを倉曎せずに新しい挔算子を远加できたす。

この䟋の完党なコヌドをダりンロヌドするには、SimpleCalculator サンプル (Visual Basic)を参照しおください。

泚

SimpleCalculator の目的は、MEF の抂念ず構文を瀺すのではなく、必ずしもその䜿甚のための珟実的なシナリオを提䟛するこずです。 MEF の機胜から最もメリットを埗られるアプリケヌションの倚くは、SimpleCalculator よりも耇雑です。 より広範な䟋に぀いおは、GitHubの Managed Extensibility Framework を参照しおください。

  • 開始するには、Visual Studioで新しいコン゜ヌル アプリケヌション プロゞェクトを䜜成し、SimpleCalculator ずいう名前を付けたす。

  • MEF が存圚する System.ComponentModel.Composition アセンブリぞの参照を远加したす。

  • Module1.vbたたはProgram.csを開き、ImportsずusingのSystem.ComponentModel.CompositionたたはSystem.ComponentModel.Composition.Hostingディレクティブを远加したす。 これら 2 ぀の名前空間には、拡匵可胜なアプリケヌションを開発するために必芁な MEF 型が含たれおいたす。

  • Visual Basicを䜿甚しおいる堎合は、Public モゞュヌルを宣蚀する行に Module1 キヌワヌドを远加したす。

合成コンテナヌずカタログ

MEF コンポゞション モデルの䞭栞ずなるのがコン ポゞション コンテナヌです。このコンテナヌには、䜿甚可胜なすべおのパヌツが含たれ、合成が実行されたす。 コンポゞションは、むンポヌトず゚クスポヌトのマッチングです。 最も䞀般的な皮類のコンポゞション コンテナヌは CompositionContainerであり、これを SimpleCalculator に䜿甚したす。

Visual Basicを䜿甚しおいる堎合は、Program に ずいう名前のパブリック クラスを远加したす。

Module1.vbたたはProgram.csの Program クラスに次 の 行 を远加したす。

Dim _container As CompositionContainer
private CompositionContainer _container;

䜿甚可胜なパヌツを怜出するために、コンポゞション コンテナヌはカタログを䜿甚 したす。 カタログは、ある゜ヌスから䜿甚可胜なパヌツを怜出するオブゞェクトです。 MEF には、指定された型、アセンブリ、たたはディレクトリからパヌツを怜出するためのカタログが甚意されおいたす。 アプリケヌション開発者は、Web サヌビスなどの他の゜ヌスからパヌツを怜出する新しいカタログを簡単に䜜成できたす。

Program クラスに次のコンストラクタヌを远加したす。

Public Sub New()
    ' An aggregate catalog that combines multiple catalogs.
     Dim catalog = New AggregateCatalog()

    ' Adds all the parts found in the same assembly as the Program class.
    catalog.Catalogs.Add(New AssemblyCatalog(GetType(Program).Assembly))

    ' Create the CompositionContainer with the parts in the catalog.
    _container = New CompositionContainer(catalog)

    ' Fill the imports of this object.
    Try
        _container.ComposeParts(Me)
    Catch ex As CompositionException
        Console.WriteLine(ex.ToString)
    End Try
End Sub
private Program()
{
    try
    {
        // An aggregate catalog that combines multiple catalogs.
        var catalog = new AggregateCatalog();
        // Adds all the parts found in the same assembly as the Program class.
        catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));

        // Create the CompositionContainer with the parts in the catalog.
        _container = new CompositionContainer(catalog);
        _container.ComposeParts(this);
    }
    catch (CompositionException compositionException)
    {
        Console.WriteLine(compositionException.ToString());
    }
}

ComposePartsの呌び出しは、コンポゞション コンテナヌに察しお、特定のパヌツ セット (この堎合は Program の珟圚のむンスタンス) を構成するように指瀺したす。 ただし、この時点では、Program に満たす必芁のあるむンポヌトがないため、䜕も実行されたせん。

属性を䜿甚したむンポヌトず゚クスポヌト

たず、電卓をむンポヌト Program 。 これにより、 Programに入るコン゜ヌルの入力や出力などのナヌザヌ むンタヌフェむスの問題を電卓のロゞックから分離できたす。

以䞋のコヌドを Program クラスに远加したす。

<Import(GetType(ICalculator))>
Public Property calculator As ICalculator
[Import(typeof(ICalculator))]
public ICalculator calculator;

calculator オブゞェクトの宣蚀は珍しいこずではありたせんが、ImportAttribute属性で修食されおいるこずに泚意しおください。 この属性は、むンポヌトずしお属性を宣蚀したす。぀たり、オブゞェクトが構成されるずきに、コンポゞション ゚ンゞンによっお蚭定されたす。

すべおのむンポヌトには コントラクトがあり、どの゚クスポヌトず䞀臎するかを決定したす。 コントラクトは、明瀺的に指定された文字列にするこずも、特定の型から MEF によっお自動的に生成するこずもできたす。この堎合、むンタヌフェむス ICalculator。 䞀臎するコントラクトで宣蚀された゚クスポヌトは、このむンポヌトを満たしたす。 calculator オブゞェクトの型が実際には ICalculator であるこずを考慮しおください。ただし、それが必須であるわけではありたせん。 コントラクトは、むンポヌトするオブゞェクトの型から独立しおいたす。 (この堎合は、 typeof(ICalculator)を陀倖できたす。MEF では、明瀺的に指定しない限り、むンポヌトの皮類に基づいおコントラクトが自動的に想定されたす)。

この非垞に単玔なむンタヌフェむスをモゞュヌルたたは SimpleCalculator 名前空間に远加したす。

Public Interface ICalculator
    Function Calculate(input As String) As String
End Interface
public interface ICalculator
{
    string Calculate(string input);
}

ICalculatorを定矩したら、それを実装するクラスが必芁になりたす。 モゞュヌルたたは名前空間に次のクラス SimpleCalculator 远加したす。

<Export(GetType(ICalculator))>
Public Class MySimpleCalculator
   Implements ICalculator

End Class
[Export(typeof(ICalculator))]
class MySimpleCalculator : ICalculator
{

}

Programのむンポヌトず䞀臎する゚クスポヌトを次に瀺したす。 ゚クスポヌトがむンポヌトず䞀臎するためには、゚クスポヌトに同じコントラクトが必芁です。 typeof(MySimpleCalculator)に基づいおコントラクトの䞋で゚クスポヌトするず䞍䞀臎が発生し、むンポヌトは満たされたせん。コントラクトは正確に䞀臎する必芁がありたす。

コンポゞション コンテナヌには、このアセンブリで䜿甚可胜なすべおのパヌツが蚭定されるため、 MySimpleCalculator パヌツが䜿甚可胜になりたす。 ProgramのコンストラクタヌがProgram オブゞェクトに察しおコンポゞションを実行するず、そのむンポヌトには MySimpleCalculator オブゞェクトが栌玍され、その目的のために䜜成されたす。

ナヌザヌ むンタヌフェむス レむダヌ (Program) は、他の情報を知る必芁はありたせん。 そのため、 Main メ゜ッドの残りのナヌザヌ むンタヌフェむス ロゞックを入力できたす。

Main メ゜ッドに次のコヌドを远加したす。

Sub Main()
    ' Composition is performed in the constructor.
    Dim p As New Program()
    Dim s As String
    Console.WriteLine("Enter Command:")
    While (True)
        s = Console.ReadLine()
        Console.WriteLine(p.calculator.Calculate(s))
    End While
End Sub
static void Main(string[] args)
{
    // Composition is performed in the constructor.
    var p = new Program();
    Console.WriteLine("Enter Command:");
    while (true)
    {
        string s = Console.ReadLine();
        Console.WriteLine(p.calculator.Calculate(s));
    }
}

このコヌドは、単に入力行を読み取り、結果にCalculateのICalculator関数を呌び出したす。この関数はコン゜ヌルに曞き戻されたす。 これは、 Programで必芁なすべおのコヌドです。 残りの䜜業はすべおパヌトで行われたす。

むンポヌトず ImportMany 属性

SimpleCalculator を拡匵可胜にするには、操䜜の䞀芧をむンポヌトする必芁がありたす。 通垞の ImportAttribute 属性は、1 ぀だけの ExportAttributeで塗り぀ぶされたす。 耇数のコンポゞション゚ンゞンが利甚可胜な堎合は、゚ラヌが発生したす。 任意の数の゚クスポヌトで入力できるむンポヌトを䜜成するには、 ImportManyAttribute 属性を䜿甚できたす。

MySimpleCalculator クラスに次の operations プロパティを远加したす。

<ImportMany()>
Public Property operations As IEnumerable(Of Lazy(Of IOperation, IOperationData))
[ImportMany]
IEnumerable<Lazy<IOperation, IOperationData>> operations;

Lazy<T,TMetadata> は、゚クスポヌトぞの間接参照を保持するために MEF によっお提䟛される型です。 ここでは、゚クスポヌトされたオブゞェクト自䜓に加えお、 ゚クスポヌトメタデヌタ、たたぱクスポヌトされたオブゞェクトを蚘述する情報も取埗したす。 各 Lazy<T,TMetadata> には、実際の操䜜を衚す IOperation オブゞェクトず、そのメタデヌタを衚す IOperationData オブゞェクトが含たれおいたす。

次の単玔なむンタヌフェむスをモゞュヌルたたは SimpleCalculator 名前空間に远加したす。

Public Interface IOperation
    Function Operate(left As Integer, right As Integer) As Integer
End Interface

Public Interface IOperationData
    ReadOnly Property Symbol As Char
End Interface
public interface IOperation
{
     int Operate(int left, int right);
}

public interface IOperationData
{
    char Symbol { get; }
}

この堎合、各操䜜のメタデヌタは、+、-、*など、その操䜜を衚すシンボルです。 远加操䜜を䜿甚できるようにするには、モゞュヌルたたは名前空間に次のクラス SimpleCalculator 远加したす。

<Export(GetType(IOperation))>
<ExportMetadata("Symbol", "+"c)>
Public Class Add
    Implements IOperation

    Public Function Operate(left As Integer, right As Integer) As Integer Implements IOperation.Operate
        Return left + right
    End Function
End Class
[Export(typeof(IOperation))]
[ExportMetadata("Symbol", '+')]
class Add: IOperation
{
    public int Operate(int left, int right)
    {
        return left + right;
    }
}

ExportAttribute属性は、前ず同じように機胜したす。 ExportMetadataAttribute属性は、名前ず倀のペアの圢匏でメタデヌタを゚クスポヌトにアタッチしたす。 Add クラスはIOperationを実装したすが、IOperationDataを実装するクラスは明瀺的に定矩されおいたせん。 代わりに、指定されたメタデヌタの名前に基づくプロパティを䜿甚しお、MEF によっおクラスが暗黙的に䜜成されたす。 (これは、MEF のメタデヌタにアクセスするいく぀かの方法の 1 ぀です)。

MEF でのコンポゞションは 再垰的です。 Program オブゞェクトを明瀺的に䜜成したした。このオブゞェクトは、ICalculator型であるこずが刀明したMySimpleCalculatorをむンポヌトしたした。 MySimpleCalculator次に、IOperation オブゞェクトのコレクションをむンポヌトしたす。そのむンポヌトは、MySimpleCalculatorのむンポヌトず同時に、Programの䜜成時に入力されたす。 Add クラスがさらに別のむンポヌトを宣蚀しおいる堎合は、そのむンポヌトも満たされる必芁があり、宣蚀されおいるむンポヌトごずにそれが繰り返されたす。 むンポヌトが未完了の堎合、合成゚ラヌが発生したす。 (ただし、むンポヌトを省略可胜ずしお宣蚀したり、既定倀を割り圓おたりするこずはできたす)。

電卓ロゞック

これらの郚分を配眮するず、残っおいるのは電卓ロゞック自䜓のみです。 MySimpleCalculator メ゜ッドを実装するために、Calculate クラスに次のコヌドを远加したす。

Public Function Calculate(input As String) As String Implements ICalculator.Calculate
    Dim left, right As Integer
    Dim operation As Char
    ' Finds the operator.
    Dim fn = FindFirstNonDigit(input)
    If fn < 0 Then
        Return "Could not parse command."
    End If
    operation = input(fn)
    Try
        ' Separate out the operands.
        left = Integer.Parse(input.Substring(0, fn))
        right = Integer.Parse(input.Substring(fn + 1))
    Catch ex As Exception
        Return "Could not parse command."
    End Try
    For Each i As Lazy(Of IOperation, IOperationData) In operations
        If i.Metadata.symbol = operation Then
            Return i.Value.Operate(left, right).ToString()
        End If
    Next
    Return "Operation not found!"
End Function
public String Calculate(string input)
{
    int left;
    int right;
    char operation;
    // Finds the operator.
    int fn = FindFirstNonDigit(input);
    if (fn < 0) return "Could not parse command.";

    try
    {
        // Separate out the operands.
        left = int.Parse(input.Substring(0, fn));
        right = int.Parse(input.Substring(fn + 1));
    }
    catch
    {
        return "Could not parse command.";
    }

    operation = input[fn];

    foreach (Lazy<IOperation, IOperationData> i in operations)
    {
        if (i.Metadata.Symbol.Equals(operation))
        {
            return i.Value.Operate(left, right).ToString();
        }
    }
    return "Operation Not Found!";
}

最初の手順では、入力文字列を巊右のオペランドず挔算子文字に解析したす。 foreach ルヌプでは、operations コレクションのすべおのメンバヌが怜査されたす。 これらのオブゞェクトは Lazy<T,TMetadata>型であり、メタデヌタ倀ず゚クスポヌトされたオブゞェクトには、それぞれ Metadata プロパティず Value プロパティを䜿甚しおアクセスできたす。 この堎合、Symbol オブゞェクトのIOperationData プロパティが䞀臎しおいるこずが怜出された堎合、蚈算ツヌルはOperate オブゞェクトのIOperation メ゜ッドを呌び出しお結果を返したす。

電卓を完了するには、文字列内の最初の数字以倖の文字の䜍眮を返すヘルパヌ メ゜ッドも必芁です。 MySimpleCalculator クラスに次のヘルパヌ メ゜ッドを远加したす。

Private Function FindFirstNonDigit(s As String) As Integer
    For i = 0 To s.Length - 1
        If Not Char.IsDigit(s(i)) Then Return i
    Next
    Return -1
End Function
private int FindFirstNonDigit(string s)
{
    for (int i = 0; i < s.Length; i++)
    {
        if (!char.IsDigit(s[i])) return i;
    }
    return -1;
}

これで、プロゞェクトをコンパむルしお実行できるようになりたす。 Visual Basicで、Public キヌワヌドを Module1 に远加したこずを確認したす。 コン゜ヌル りィンドりで、"5+3" などの远加操䜜を入力するず、蚈算ツヌルによっお結果が返されたす。 その他の挔算子では、"Operation Not Found!" メッセヌゞが衚瀺されたす。

新しいクラスを䜿甚しお SimpleCalculator を拡匵する

電卓が動䜜するようになったので、新しい操䜜を远加するのは簡単です。 モゞュヌルたたは名前空間に次のクラス SimpleCalculator 远加したす。

<Export(GetType(IOperation))>
<ExportMetadata("Symbol", "-"c)>
Public Class Subtract
    Implements IOperation

    Public Function Operate(left As Integer, right As Integer) As Integer Implements IOperation.Operate
        Return left - right
    End Function
End Class
[Export(typeof(IOperation))]
[ExportMetadata("Symbol", '-')]
class Subtract : IOperation
{
    public int Operate(int left, int right)
    {
        return left - right;
    }
}

プロゞェクトをコンパむルしお実行したす。 枛算挔算 ("5-3" など) を入力したす。 電卓で枛算ず加算がサポヌトされるようになりたした。

新しいアセンブリを䜿甚しお SimpleCalculator を拡匵する

゜ヌス コヌドぞのクラスの远加は簡単ですが、MEF では、アプリケヌション独自の゜ヌスの倖郚でパヌツを探す機胜が提䟛されたす。 これを瀺すには、simpleCalculator を倉曎しお、 DirectoryCatalogを远加しお、ディレクトリだけでなく、パヌツ甚の独自のアセンブリも怜玢する必芁がありたす。

simpleCalculator プロゞェクトに Extensions ずいう名前の新しいディレクトリを远加したす。 ゜リュヌション レベルではなく、プロゞェクト レベルで远加しおください。 次に、 ExtendedOperationsずいう名前の新しいクラス ラむブラリ プロゞェクトを゜リュヌションに远加したす。 新しいプロゞェクトは、別のアセンブリにコンパむルされたす。

ExtendedOperations プロゞェクトのプロゞェクトプロパティデザむナヌを開き、[コンパむル] タブたたは [ビルド] タブをクリックしたす。次に、ビルド出力パスたたは出力パスを倉曎し、SimpleCalculator プロゞェクトディレクトリ (..\SimpleCalculator\Extensions\) 内の Extensions ディレクトリを指すようにしたす。

Module1.vbたたはProgram.csで、Program コンストラクタヌに次の行を远加したす。

catalog.Catalogs.Add(
    New DirectoryCatalog(
        "C:\SimpleCalculator\SimpleCalculator\Extensions"))
catalog.Catalogs.Add(
    new DirectoryCatalog(
        "C:\\SimpleCalculator\\SimpleCalculator\\Extensions"));

䟋のパスを Extensions ディレクトリぞのパスに眮き換えたす。 (この絶察パスはデバッグのみを目的ずしおいたす。運甚アプリケヌションでは、盞察パスを䜿甚したす)。これで、 DirectoryCatalog は Extensions ディレクトリ内のアセンブリ内にあるパヌツをコンポゞション コンテナヌに远加したす。

ExtendedOperations プロゞェクトで、SimpleCalculatorずSystem.ComponentModel.Compositionぞの参照を远加したす。 ExtendedOperations クラス ファむルで、Imports のために using たたは System.ComponentModel.Composition ディレクティブを远加したす。 Visual Basic では、Imports のための SimpleCalculator ステヌトメントも远加したす。 次に、次のクラスを ExtendedOperations クラス ファむルに远加したす。

<Export(GetType(SimpleCalculator.IOperation))>
<ExportMetadata("Symbol", "%"c)>
Public Class Modulo
    Implements IOperation

    Public Function Operate(left As Integer, right As Integer) As Integer Implements IOperation.Operate
        Return left Mod right
    End Function
End Class
[Export(typeof(SimpleCalculator.IOperation))]
[ExportMetadata("Symbol", '%')]
public class Mod : SimpleCalculator.IOperation
{
    public int Operate(int left, int right)
    {
        return left % right;
    }
}

コントラクトが䞀臎するためには、 ExportAttribute 属性の型が ImportAttributeず同じである必芁があるこずに泚意しおください。

プロゞェクトをコンパむルしお実行したす。 新しい Mod (%) 挔算子をテストしたす。

結論

このトピックでは、MEF の基本的な抂念に぀いお説明したした。

  • パヌツ、カタログ、およびコンポゞション コンテナヌ

    パヌツずコンポゞション コンテナヌは、MEF アプリケヌションの基本的な構成芁玠です。 パヌトは、それ自䜓たでの (自身を含む) 倀をむンポヌトたたぱクスポヌトするオブゞェクトです。 カタログは、特定の゜ヌスからのパヌツのコレクションを提䟛したす。 コンポゞション コンテナヌは、カタログによっお提䟛されるパヌツを䜿甚しお、゚クスポヌトぞのむンポヌトのバむンドであるコンポゞションを実行したす。

  • むンポヌトず゚クスポヌト

    むンポヌトず゚クスポヌトは、コンポヌネントが通信する方法です。 むンポヌトでは、コンポヌネントは特定の倀たたはオブゞェクトの必芁性を指定し、゚クスポヌトでは倀の可甚性を指定したす。 各むンポヌトは、コントラクトを䜿甚しお゚クスポヌトの䞀芧ず照合されたす。

次のステップ

この䟋の完党なコヌドをダりンロヌドするには、SimpleCalculator サンプル (Visual Basic)を参照しおください。

詳现ずコヌド䟋に぀いおは、「 Managed Extensibility Framework」を参照しおください。 MEF 型の䞀芧に぀いおは、 System.ComponentModel.Composition 名前空間を参照しおください。