이 문서에서는 .NET Framework 4에 도입된 관리되는 확장성 프레임워크의 개요를 제공합니다.
MEF란?
MEF(Managed Extensibility Framework)는 가볍고 확장 가능한 애플리케이션을 만들기 위한 라이브러리입니다. 이를 통해 애플리케이션 개발자는 구성 없이 확장을 검색하고 사용할 수 있습니다. 또한 확장 개발자는 코드를 쉽게 캡슐화하고 취약한 하드 종속성을 방지할 수 있습니다. MEF를 사용하면 애플리케이션 내에서뿐만 아니라 애플리케이션 간에도 확장을 다시 사용할 수 있습니다.
확장성 문제
확장성을 지원해야 하는 대규모 애플리케이션의 설계자라고 상상해 보십시오. 애플리케이션은 잠재적으로 많은 수의 더 작은 구성 요소를 포함해야 하며, 구성 요소를 만들고 실행하는 역할을 담당합니다.
문제에 대한 가장 간단한 방법은 구성 요소를 애플리케이션에 소스 코드로 포함하고 코드에서 직접 호출하는 것입니다. 여기에는 여러 가지 명백한 단점이 있습니다. 가장 중요한 것은 소스 코드를 수정하지 않고는 새 구성 요소를 추가할 수 없다는 것입니다. 예를 들어 웹 애플리케이션에서 허용될 수 있지만 클라이언트 애플리케이션에서는 작동하지 않을 수 있는 제한 사항입니다. 마찬가지로, 구성 요소가 타사에서 개발되어 소스 코드에 접근할 수 없을 수도 있고 같은 이유로 그들이 당신의 소스 코드에 접근하는 것을 허용할 수 없습니다.
약간 더 정교한 방법은 확장 지점 또는 인터페이스를 제공하여 애플리케이션과 해당 구성 요소 간의 분리를 허용하는 것입니다. 이 모델에서는 구성 요소가 구현할 수 있는 인터페이스와 애플리케이션과 상호 작용할 수 있도록 하는 API를 제공할 수 있습니다. 이렇게 하면 소스 코드 액세스가 필요한 문제가 해결되지만 여전히 고유한 문제가 있습니다.
애플리케이션은 자체적으로 구성 요소를 검색할 수 있는 용량이 부족하기 때문에 사용 가능한 구성 요소를 명시적으로 알려주어야 하며 로드해야 합니다. 이 작업은 일반적으로 구성 파일에 사용 가능한 구성 요소를 명시적으로 등록하여 수행됩니다. 즉, 구성 요소가 올바른지 확인하면 유지 관리 문제가 됩니다. 특히 업데이트를 수행할 것으로 예상되는 개발자가 아닌 최종 사용자인 경우 더욱 그러합니다.
또한 구성 요소는 애플리케이션 자체의 엄격하게 정의된 채널을 제외하고는 서로 통신할 수 없습니다. 애플리케이션 설계자가 특정 통신의 필요성을 예상하지 못한 경우 일반적으로 불가능합니다.
마지막으로 구성 요소 개발자는 구현하는 인터페이스가 포함된 어셈블리에 대한 하드 종속성을 허용해야 합니다. 따라서 둘 이상의 애플리케이션에서 구성 요소를 사용하는 것이 어렵고 구성 요소에 대한 테스트 프레임워크를 만들 때 문제가 발생할 수도 있습니다.
MEF에서 제공하는 내용
MEF는 사용 가능한 구성 요소를 명시적으로 등록하는 대신 컴퍼지션을 통해 암시적으로 검색할 수 있는 방법을 제공합니다. 파트라고 하는 MEF 구성 요소는 종속성(가져오기라고 함)과 사용할 수 있는 기능(내보내기라고 함)을 선언적으로 지정합니다. 부품(컴포넌트)이 생성될 때, MEF 구성 엔진은 다른 컴포넌트에서 제공 가능한 것으로 해당 요구 사항을 충족합니다.
이 방법은 이전 섹션에서 설명한 문제를 해결합니다. MEF 파트는 해당 기능을 선언적으로 지정하기 때문에 런타임에 검색할 수 있습니다. 즉, 애플리케이션이 하드 코딩된 참조 또는 취약한 구성 파일 없이 부품을 사용할 수 있습니다. MEF를 사용하면 애플리케이션을 인스턴스화하거나 어셈블리를 로드하지 않고도 메타데이터로 파트를 검색하고 검사할 수 있습니다. 따라서 확장을 로드해야 하는 시기와 방법을 신중하게 지정할 필요가 없습니다.
제공된 내보내기 외에도 파트는 가져오기를 지정할 수 있으며, 이 항목은 다른 파트로 채워집니다. 이렇게 하면 파트 간 통신이 가능할 뿐만 아니라 쉬워지고, 코드의 좋은 분할을 가능하게 합니다. 예를 들어 많은 구성 요소에 공통된 서비스는 별도의 부분으로 인계되고 쉽게 수정되거나 교체될 수 있습니다.
MEF 모델은 특정 애플리케이션 어셈블리에 대한 하드 종속성이 필요하지 않으므로 애플리케이션에서 애플리케이션으로 확장을 다시 사용할 수 있습니다. 또한 애플리케이션과 독립적으로 테스트 하네스를 쉽게 개발하여 확장 구성 요소를 테스트할 수 있습니다.
MEF를 사용하여 작성된 확장 가능 애플리케이션은 확장 구성 요소로 채울 수 있는 가져오기를 선언하고 애플리케이션 서비스를 확장에 노출하기 위해 내보내기를 선언할 수도 있습니다. 각 확장 구성 요소는 내보내기 선언 및 가져오기를 선언할 수도 있습니다. 이러한 방식으로 확장 구성 요소 자체는 자동으로 확장할 수 있습니다.
MEF를 사용할 수 있는 위치
MEF는 .NET Framework 4의 필수적인 부분이며 .NET Framework가 사용되는 모든 곳에서 사용할 수 있습니다. 클라이언트 애플리케이션에서 WINDOWS Forms, WPF 또는 기타 기술을 사용하든, ASP.NET 사용하는 서버 애플리케이션에서 MEF를 사용할 수 있습니다.
MEF 및 MAF
이전 버전의 .NET Framework는 애플리케이션이 확장을 격리하고 관리할 수 있도록 설계된 MAF(관리되는 추가 기능 프레임워크)를 도입했습니다. MAF의 초점은 MEF보다 약간 더 높으며 확장 격리 및 어셈블리 로드 및 언로드에 중점을 두고 있으며 MEF의 초점은 검색 기능, 확장성 및 이식성에 있습니다. 두 프레임워크는 원활하게 상호 운용되며 단일 애플리케이션이 둘 다 활용할 수 있습니다.
SimpleCalculator: 예제 애플리케이션
MEF에서 수행할 수 있는 작업을 확인하는 가장 간단한 방법은 간단한 MEF 애플리케이션을 빌드하는 것입니다. 이 예제에서는 SimpleCalculator라는 매우 간단한 계산기를 빌드합니다. SimpleCalculator의 목표는 기본 산술 명령을 "5+3" 또는 "6-2" 형식으로 수락하고 올바른 답변을 반환하는 콘솔 애플리케이션을 만드는 것입니다. MEF를 사용하면 애플리케이션 코드를 변경하지 않고도 새 연산자를 추가할 수 있습니다.
이 예제의 전체 코드를 다운로드하려면 SimpleCalculator 샘플(Visual Basic)을 참조하세요.
비고
SimpleCalculator의 목적은 MEF의 개념과 구문을 보여 주는 것이 아니라 반드시 사용하기 위한 현실적인 시나리오를 제공하는 것입니다. MEF의 강력한 기능을 통해 가장 많은 이점을 얻을 수 있는 많은 애플리케이션은 SimpleCalculator보다 더 복잡합니다. 보다 광범위한 예제는 GitHub의 관리되는 확장성 프레임워크 를 참조하세요.
시작하려면 Visual Studio에서 새 콘솔 애플리케이션 프로젝트를 만들고 이름을 지정합니다
SimpleCalculator
.MEF가 있는 어셈블리에
System.ComponentModel.Composition
대한 참조를 추가합니다.Module1.vb 또는 Program.cs를 열고,
Imports
및using
지시문을 추가하기 위해System.ComponentModel.Composition
또는System.ComponentModel.Composition.Hosting
지시문을 추가하세요. 이러한 두 네임스페이스에는 확장 가능한 애플리케이션을 개발하는 데 필요한 MEF 형식이 포함되어 있습니다.Visual Basic을 사용하는 경우
Public
모듈을 선언하는 줄에Module1
키워드를 추가합니다.
컴퍼지션 컨테이너 및 카탈로그
MEF 컴퍼지션 모델의 핵심은 사용 가능한 모든 부분을 포함하고 컴퍼지션을 수행하는 컴퍼지션 컨테이너입니다. 수입과 수출의 일치를 의미합니다. 컴퍼지션 컨테이너의 가장 일반적인 형식은 CompositionContainerSimpleCalculator에 사용됩니다.
Visual Basic을 사용하는 경우 Program
명명된 공용 클래스를 추가합니다.
Module1.vb Program
Program.cs 클래스에 다음 줄을 추가합니다.
Dim _container As CompositionContainer
private CompositionContainer _container;
사용할 수 있는 파트를 검색하기 위해 컴퍼지션 컨테이너는 카탈로그를 사용합니다. 카탈로그는 일부 원본에서 검색된 사용 가능한 파트를 만드는 개체입니다. MEF는 제공된 형식, 어셈블리 또는 디렉터리에서 파트를 검색하는 카탈로그를 제공합니다. 애플리케이션 개발자는 웹 서비스와 같은 다른 원본에서 파트를 검색하는 새 카탈로그를 쉽게 만들 수 있습니다.
클래스에 다음 생성자를 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
클래스에 다음 코드를 추가합니다.
<Import(GetType(ICalculator))>
Public Property calculator As ICalculator
[Import(typeof(ICalculator))]
public ICalculator calculator;
calculator
객체의 선언 자체는 특별하지 않지만 ImportAttribute 속성으로 장식되어 있습니다. 이 특성은 가져오기로 선언합니다. 즉, 개체가 작성될 때 컴퍼지션 엔진에 의해 채워집니다.
모든 가져오기에는 일치하는 내보내기를 결정하는 계약이 있습니다. 계약은 명시적으로 지정된 문자열이거나 지정된 형식(이 경우 인터페이스 ICalculator
)에서 MEF에 의해 자동으로 생성될 수 있습니다. 일치하는 계약으로 선언된 모든 내보내기가 이 가져오기를 수행합니다. 실제로 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
나머지 작업은 모든 각 부분에서 이루어질 것입니다.
Import 및 ImportMany 특성
SimpleCalculator를 확장하려면 작업 목록을 가져와야 합니다. 일반 ImportAttribute 특성은 하나의 ExportAttribute로만 채워집니다. 둘 이상의 사용 가능한 경우 컴퍼지션 엔진에서 오류가 발생합니다. ImportManyAttribute 속성을 사용하면 어떤 수의 내보내기로도 채울 수 있는 가져오기를 만들 수 있습니다.
클래스에 다음 작업 속성을 MySimpleCalculator
추가합니다.
<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에서 메타데이터에 액세스하는 여러 가지 방법 중 하나입니다.)
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"과 같은 추가 작업을 입력하고 계산기는 결과를 반환합니다. 다른 연산자는 "연산을 찾을 수 없음!" 메시지를 표시합니다.
새 클래스를 사용하여 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는 파트에 대한 애플리케이션의 자체 소스 외부에서 볼 수 있는 기능을 제공합니다. 이를 설명하기 위해서는 DirectoryCatalog 태그를 추가하여 디렉터리와 자신의 어셈블리 안에서 부품을 검색하도록 SimpleCalculator를 수정해야 합니다.
SimpleCalculator 프로젝트에 명명된 Extensions
새 디렉터리를 추가합니다. 솔루션 수준이 아닌 프로젝트 수준에서 추가해야 합니다. 그런 다음, 솔루션에 새 클래스 라이브러리 프로젝트인 를 추가합니다 ExtendedOperations
. 새 프로젝트는 별도의 어셈블리로 컴파일됩니다.
ExtendedOperations 프로젝트에 대한 프로젝트 속성 디자이너를 열고 컴파일 또는 빌드 탭을 클릭합니다. SimpleCalculator 프로젝트 디렉터리(.)의 확장 디렉터리를 가리키도록 빌드 출력 경로 또는 출력 경로를 변경합니다. \SimpleCalculator\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 이제 확장 디렉터리의 어셈블리에 있는 모든 파트를 컴퍼지션 컨테이너에 추가합니다.
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 참조하세요.
.NET