[MEF] 4. Import 선언

Managed Extensibility Framework 2009. 4. 7. 00:32 Posted by POWERUMC
Import 선언
 
MEF 의 구성 요소에 System.ComponentModel.Composition.ImportAttribute 특성을 선언하여 Import 를 선언할 수 있습니다. Import 는 Export 와 사용 방법이 매우 유사합니다. Import 는 프로퍼티(Properties), 필드(Fields), 생성자(Constructors) 에 선언할 수 있으며, 계약된 Export 구성 요소들을 Import 할 수 있습니다.
 
 
Property Import
 
프로퍼티로 값을 가져오기 위해 ImportAttribute 특성을 선언하면 됩니다.
 
Import 특성은 세 가지의 시그너처(Signature) 를 제공합니다.
 
public ImportAttribute();
public ImportAttribute(string contractName);
public ImportAttribute(Type contractType);
 
일반적으로 타입을 명시하지 않을 경우 프로퍼티의 타입이 Export 의 계약(Contract) 을 결정하게 됩니다.
 
아래는 프로퍼티에 Import 를 사용하는 방법입니다.
 

[Import]
MessageProcess MessageProcess { get; set; }

 
 
Field Import
 
필드의 Import 는 프로퍼티에 Import 를 선언하는 방법과 동일합니다.
 

[Import]
MessageProcess _messageProcess;

 
 
Constructor Parameters (생성자 파라메터)
 
Constructor Parameters 는 ImportingConstructor 특성을 사용하여 정의합니다. 특히 Constructor Parameters 는 여러 구성 요소를 사용하기 위해 프로퍼티 또는 필드로 선언되는 Import 의 선언을 생략할 수 있어 편리하게 사용할 수 있습니다. 또한, 암시적인 Import 가 가능하기 때문에 수동적으로 이것을 제어할 필요가 없으며, 구성 요소의 교체가 매우 용이합니다.
 
아래의 코드는 ImportingConstructor 특성을 이용하여 암시적으로 Import 하는 예입니다.
 

[Export]
public class Controller
{
   public View CurrentView { get; set; }
   public Model CurrentModel { get; set; }
 
   [ImportingConstructor]
   public Controller(View view, Model model)
   {
       this.CurrentView = view;
       this.CurrentModel = model;
   }
}

 
명시적인 Import 를 하기 위해서는 생성자 파라메터에 ImportAttribute 특성을 명시해 주면 됩니다.
 
아래는 Constructor Parameters 예의 전체 소스 코드입니다.
 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
 
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
 
namespace ImportSample
{
   class Program
   {
       [STAThread]
       static void Main(string[] args)
       {
             Program p = new Program();
             p.Run();
       }
      
       private void Run()
       {
              var catalog = new AggregateCatalog();
             catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
 
             var container = new CompositionContainer(catalog);
             var batch = new CompositionBatch();
             batch.AddPart(this);
             container.Compose(batch);
 
             var controller = container.GetExportedObject<Controller>();
 
            
             Console.WriteLine(controller.CurrentView.ToString());
             Console.WriteLine(controller.CurrentModel.ToString());
       }
   }
 
   [Export]
   public class Controller
   {
       public View CurrentView { get; set; }
       public Model CurrentModel { get; set; }
 
       [ImportingConstructor]
       public Controller(View view, Model model)
       {
             this.CurrentView = view;
             this.CurrentModel = model;
       }
   }
 
   [Export]
   public class View
   {
       public override string ToString()
       {
             return "Export View";
       }
   }
 
   [Export]
   public class Model
   {
       public override string ToString()
       {
             return "Export Model";
       }
   }
}

 
실행 결과는
 
[그림1] Constructor Parameters 예제 소스 코드 실행 결과
 
 
Importing Collection
 
MEF 는 Composable Container 의 모든 Contract 의 인스턴스를 컬렉션으로 가져올 수 있습니다. MEF 는 플러그인 모델(Plugin Model) 로써 구성 요소를 교체와 추가/제거가 용이하다고 하였습니다. 이러한 구성 요소가 동적으로 교체 또는 컨테이너에 의해 관리가 되면서 구성 요소는 업데이트 또는 Recomposable(재구성 가능한) 될 수 있습니다.
 
Contract 기반의 MEF 구성 요소는 동적인(Dynamic)한 환경을 제공하며, 이것을 관리하기 위해 컬렉션으로 제어할 수 있습니다.
 
아래는 Importing Collection 의 예제 소스 코드입니다.
 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
 
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
 
namespace ImportSample
{
   class Program
   {
       [Import]
       IEnumerable<IMessageSender> MessageSenders;
 
       [STAThread]
       static void Main(string[] args)
       {
             Program p = new Program();
             p.Run();
 
             foreach (var sender in p.MessageSenders)
             {
                    sender.Say();
             }
       }
      
       private void Run()
       {
             var catalog = new AggregateCatalog();
             catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
 
             var container = new CompositionContainer(catalog);
             var batch = new CompositionBatch();
             batch.AddPart(this);
             container.Compose(batch);
       }
   }
 
   public interface IMessageSender
   {
       void Say();
   }
 
   [Export(typeof(IMessageSender))]
   public class PhoneMessageSender : IMessageSender
   {
       public void Say()
       {
             Console.WriteLine("Message Send - Phone");
       }
   }
 
   [Export(typeof(IMessageSender))]
   public class EMailMessageSender : IMessageSender
   {
       public void Say()
       {
             Console.WriteLine("Message Send - EMail");
       }
   }
}

 
IMessageSender 인터페이스를 구현한 구성 요소를 컬렉션으로 루핑하여 호출한 결과입니다.
 
[그림2] Importing Collection 예제 소스 코드 실행 결과
 
 
INotifyImportSatisfaction
 
INotifyImportSatisfaction 인터페이스는 Import 처리가 완료가 되었을 때 통보되는 인터페이스 입니다. System.ComponentModel.Composition.INotifyImportSatisfaction 인터페이스는 ImportCompleted() 메서드만 구현하면 됩니다. 클래스내 모든 Import 처리가 완료가 되었을 경우 ImportCompleted() 메서드가 호출됩니다.
 
아래 소스 코드는 INotifyImportSatisfaction 인터페이스를 구현한 예 입니다.
 

class Program : INotifyImportSatisfaction
{
 
   public void ImportCompleted()
   {
       Console.WriteLine("Completed");
   }
 
}

 
 
 
MEF 다시 보기
 
MEF 는 마치 어린 아이들이 좋아하던 조립 로봇을 보는 듯한 인상입니다. 로봇의 몸체만 있다면 팔, 다리를 끼워 로봇을 어렵지 않게 완성하는 것처럼 말입니다. 플라스틱 로봇에게 강철 옷을 입히고 싶다면, 로봇을 전부 때려부시고 새로 만들지 않고서도 MEF 를 이용하면 가능합니다. 그리고 칼과 방패를 채워주고 싶다면 그렇게 하시면 됩니다.
 
[그림3] MEF 와 조립 로봇 (그림 출처는 여기)
 
MEF 를 볼수록 하나의 작은 SOA(Service Oriented Architecture) 라고 봐도 무방할 것 같습니다. (비교하는 것이 무리이긴 하지만…) MEF 의 플러그인 모델(Plugin Model) 은 느슨한 결합(Loose Coupling) 으로 Service 와 EndPoint 의 Contract 기반의 유연한 확장성을 제공해 줍니다. 아마도 단시간내에 새로운 아키텍처의 모델로써 주목을 받을 수 있지 않을까 기대해봅니다.

'Managed Extensibility Framework' 카테고리의 다른 글

[MEF] 6. Lazy Exports  (0) 2009.04.13
[MEF] 5. Catalog 사용  (0) 2009.04.09
[MEF] 3. Export 선언  (0) 2009.03.29
[MEF] 2. Parts 와 Contracts 선언  (0) 2009.03.22
[MEF] 1. Managed Extensibility Framework 이란?  (2) 2009.03.16