Querying the CompositionContainer
 
CompositionContainer 의 Exported 구성 요소를 취득하기 위해서는 컨테이너에 하나의 구성 요소만이 존재해야 합니다. 쿼리(Query) 를 통해 이러한 객체들이 여러 개 존재할 경우 MEF 는 예외를 발생하게 됩니다.
 
바로 아래와 같은 경우이죠.
l 하나의 인스턴스를 요청할 때, 인스턴스를 찾지 못했을 경우
l 하나의 인스턴스를 요청할 때, 인스턴스가 여러 개일 경우
 
GetExportedObject
 
일반적으로 ExportAttribute 에 인자가 전달되지 않은 경우는 클래스의 타입이 키 값이 되어, 아래와 같이 구성 요소를 취득할 수 있습니다.
 
class Program
{
        static void Main(string[] args)
        {
               var container = new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
              
               var export = container.GetExportedObject<Export1>();
               export.Say();
 
               Console.ReadKey();
        }
}
 
[Export]
class Export1
{
        public void Say()
        {
               Console.WriteLine("Export1 Say..");
        }
}
 
 
만약, ExportAttribute 에 Contract Name 이 선언이 될 경우는 클래스의 타입 정보와 Contract Name 이 일치해야 구성요소를 취득할 수 있습니다.
 
class Program
{
        static void Main(string[] args)
        {
               var container = new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
              
               var export = container.GetExportedObject<Export2>("export2");
               export.Say();
 
               Console.ReadKey();
        }
}
 
[Export("export2")]
public class Export2
{
        public void Say()
        {
               Console.WriteLine("Export2 Say..");
        }
}
 
 
GetExport
 
만약 여러 개의 구성 요소의 인스턴스가 필요하다면 GetExport 메서드를 통해 Export 의 구성 정보를 가져오면 됩니다.
 
var exports = container.GetExport<Export1>();
exports.GetExportedObject().Say();
 
필요하다면 ExportAttribute 의 Contract Name 으로 질의(Query) 할 수 있습니다.
 
var exports = container.GetExport<Export2>("export2");
exports.GetExportedObject().Say();
 
아쉽게도 MEF Preview 4 까지 지원하던 C# 3.0 의 Expression 을 통해 질의하는 방법은 MEF Preview 5 이후 없어진 것이 아쉽네요.
 
GetExportedObjectOrDefault
 
일반적으로 MEF 에서는 질의(Query) 결과가 없을 경우 예외를 발생하게 되는데, GetExportedObjectOrDefault 메서드를 통해 결과가 없을 경우 Null 값으로 대체할 수 있습니다.
 
var obj = container.GetExportedObjectOrDefault<Export1>("A");
if( obj != null )
        obj.Say();
 
 

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

MEF 는 Generic Type 을 지원하지 않는다!  (0) 2010.01.29
MEF Preview 6 공개  (0) 2009.07.20
[MEF] 9. Recomposition  (1) 2009.04.19
[MEF] 8. Strongly Typed Metadata  (0) 2009.04.16
[MEF] 7. Exports and Metadata  (0) 2009.04.16

Welcome to Dynamic C#(2) - Wanna be a polyglot.

C# 2009. 5. 17. 16:25 Posted by 알 수 없는 사용자

- 자넨 왜 그렇게 언어에 집착하는고?

넵, 확실히 저는 언어에 쫌 집착하는 편이긴 합니다. 우리가 말하고 쓰는언어도 꽤나 집착하는 편입니다. 언어를 제대로 배우려고 노력하다보면, 더 재밌는 걸 많이 접할 수 있게 되고 그 언어뿐만 아니라 언어를 쓰는 사람들의 사고방식도 아주 조금씩 이해하게 되기 때문이죠. 뭔가 보고싶은게 있는데 그게 제가 모르는 언어로 되어 있어서 못보는건 조금 슬픈일인거 같습니다. 개인적으로 부족한 실력이지만, 미드&일드를 아주 재밌게 즐기고 있습니다.

프로그래밍 언어도 비슷한 의미에서 집착하게 되는게 아닐까 싶습니다. 프로그래밍 언어에는 그 언어를 만들고 지지하는 사람들의 사고방식도 같이 배울 수 있게 되고, 점점 재밌게 할수 있는게 늘어나기 때문이죠. 최근에 언어에 대해서 아주 부족한 의견이지만 글을 썼던 적이 있습니다. 관심있으신 분은 보시고 따쓰한 피드백 주시면 완전 감사하겠습니다. 

아무튼 그런의미에서 F#에 C#에 Axum까지 건드려보고 있는거지요. 줏대가 없다거나 바람기가 있다거나 뭐 그런건 아닙니다. 그럼 본론으로 들어가서, 지난번엔 동적C#에 대한 이야기를 조금 드렸었습니다. 하지만 정작 알고 싶은건 dynamic키워드란게 생겼고 대충 오리꽥꽥 어쩌구 저쩌구 하는건 알겠는데, 어디다 써먹는거란 말이더냐? 뭐 그런거겠죠. 그래서 쌩초보이지만, 최대한 그런관점에서 접근해보고자 합니다. 그 첫번째가 실제로 프로젝트를 하다가 하나 느낀게 있어서 그걸 적어보고자 합니다. 



- 시나리오
(제가 모르는 해결방법이 있을수도 있습니다. 그럴땐 따쓰한 피드백을!)

LINQ to SQL(이하 L2S)로 프로젝트를 진행중입니다만, 데이터가 추가되거나, 수정되거나 삭제될때 그 값들의 이전/이후 데이터를 포함해서 그 데이터의 고유번호(seq)를 같이 저장하는 뭐 그런 시나리오입니다. 그래서 L2S에서는 아래와 같은 방법을 제공합니다.

 

ChangeSet changeSet = db.GetChangeSet();

foreach (Customer c in changeSet.Inserts)
{
	.......
}

 

하지만, 위와 같은 코드는 한번의 SubmitChanges로 변경이 일어나는 대상 테이블이 하나라면 Generic파라미터로 처리할 수도 있겠지만(ChangeSet에서 리턴되는 객체의 타입이 object입니다), 주문과 상세주문같이 한번에 여러개의 테이블에 변경이 일어난다면, 그닥 친절하지 못한 시나리오가 되겠습니다. 그래서 그때 들었던 생각이 "아 이거 dynamic키워드를 이용해서 오리꽥꽥타이핑(duck typing)을 이용하면, 쫌 쉽게 될거 같은뎅..." 였습니다. 그래서 한번 살짝 구현해봤습니다.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace FirstDynamic
{
    class Customer
    {
        public int Seq{get; set;}
        public string Name {get; set;}        
    }

    class Company
    {
        public int Seq{get; set;}
        public string Name{get; set;}
    }

    class Project
    {
        public int Seq{get; set;}
        public string Name{get; set;}
    }

    class NoneSeqThing
    {
        public string Name{get; set;}
    }

    class Logger
    {
        public void WriteLog(dynamic entity)
        {
            try{
                Console.WriteLine(entity.Seq);
            }
            catch(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
            {
                Console.WriteLine("Exception : " + ex.Message);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {            
            Logger logger = new Logger();

            Customer customer = new Customer
            {
                Seq = 1,
                Name = "Boram"
            };

            Company company = new Company
            {
                Seq = 6,
                Name = "NanoSoft"
            };

            Project project = new Project
            {
                Seq = 108,
                Name = ".NET 99.9"
            };

            NoneSeqThing noneSeqThing = new NoneSeqThing
            {
                Name = "None Seq Thing"
            };

            object[] entities = new object[] { customer, company, project, noneSeqThing };

            foreach (object entity in entities)
            {
                logger.WriteLog(entity);
            }
        }
    }
}

 

위에서는 몇가지 객체를 선언해서 DTO를 흉내냈고, Seq가 있는 타입과 없는 타입이 있는 것을 볼 수 있습니다. 그리고 ChangeSet에서 반환되는 객체를 그냥 dynamic으로 Logger에게 넘겨주고 있습니다. 그리고 Seq멤버변수가 있으면 남기고 없으면 안남기는 식으로 다른 처리를 해주고 있습니다. 그리고 결과는 아래와 같습니다.



그렇습니다, 이런식으로 dynamic을 이용한다면 지난 포스트에서 Paul Graham아자씨가 이야기 했던 나이들고 엄한 이모 컴파일러와 좀더 편하게 대화할 수 있는 법이죠. 써놓고 보니깐 포스트가 별거 없네요. 기분 탓이 아니라 제 내공 탓이겠죠. 여담이지만, 제가 해결한 방식은 리플렉션으로 Seq프로퍼티를 검색해서 유/무를 판별하는 방식을 이용했습니다. 확실히 손이 좀더 많이 가는 방법이죠.

이렇게 여러가지 패러다임에 익숙해지고 잘 활용할 수 있게 되면, 점점 더 빠르고 경쾌한 리듬으로 코드를 작성하는 일도 가능하지 않을까 생각해봅니다. 이제 프로그래밍을 하시는 분들도 세계화에 발맞추는 속도에 걸맞게 프로그래밍언어에 대해서도  ployglot이 되어야 하지 않을까 생각합니다. 다만, 제 생각엔 그러한 노력은 프로그래머에게 족쇄를 채우는게 아니라 오히려 더 큰 자유를 주는 일이라고 생각합니다. 그럼, 또 개발하다가 dynamic의 헬프가 필요한 순간이 오면 나누도록 하겠습니다.

여담이지만, polyglot하니깐 중학교때 "핸들 이빠이 돌려"라는 한문장으로 3개국어를 자유자재로 구사하시던 한문선생님이 떠오르는 군요. ㅋ


-참고자료
1. Pro LINQ: Language Integrated Query in C# 2008, Joseph C. Rattz, Jr. , APRESS.

Welcome to Parellel world(1) - Here comes a new challenger!

C# Parallel Programming 2009. 5. 16. 16:04 Posted by 알 수 없는 사용자

-신 캐릭터의 등장.

언제나 새로운 캐릭터의 등장은 가슴을 설레이게 하는거 같습니다. 디아블로 같은 액션 RPG도, 스타크래프트같은 전략시뮬에서도, 미연시에서...... 그리고 비주얼스튜디오에서도 말이죠. Axum은 딱히 비주얼스튜디오 2010에 포함되기로 이야기 되는 언어는 아닙니다만, 왠지 2010이나 그 이후버전에선 정식으로 편입되어서 중요한 역할을 할 것같은 느낌이 들어서 아주 조금씩 소개를 드려볼까 합니다. 물론 Welcome to Parallel world에서는 Axum만 다루진 않을 거구요 기타 다른 병렬프로그래밍에 대한 이슈들을 쌩초보의 입장에서 공부하면서 정리해보고자 합니다. 신기한게 보이면 그냥 못지나치는 성격이라 시간은 부족해지는데 일은 계속해서 늘리고 있군요. 아무튼, 관심있는분들의 많은 따쓰한 피드백을 기다리며 시작해보겠습니다. 

-Axum????

Axum은 위에서 설명드린것 처럼 딱히 아직 구체적인 계획은 없고 그저 실험적으로 개발되고 있는 새로운 언어입니다. 가이드문서에서는 아래와 같이 설명을 하고 있군요.

Writing a parallel program typically requires partitioning the solution into a number of parallel tasks. Some problems are easily amenable to parallelization because the tasks can run independently of each other. In other problems the tasks have interdependencies and require coordination. ......... With Axum, we offer a language that allows programmers to arrange coordination between components in a way that is close to their natural conception of the solution. In other words, if you can model your solution in terms of interactive components, encoding it in Axum will be straightforward, and you will likely avoid many common concurrency-related bugs. 

병렬 프로그램을 작성하려면, 프로그램을 여러개의 작은 병렬작업들로 쪼개는 작업이 필요합니다. 몇가지 문제들은 애초에 서로 독립적으로 수행될 수 있으니깐 쉽게 병렬화시킬 수 있습니다. 다른 몇가지 문제들은 서로 연관되어 있기 때문에 순서를 잘 정해줘야 합니다. .... Axum은 그러한 수행순서등을 솔루션이 원래 동작해야 하는 시나리오에 근접하게 잘 정리하도록 도와주는 새로운 언어입니다. 부연 설명을 하자면, 문제해결을 위한 솔루션을 컴포넌트들의 상호작용모델로 그려낼 수 있다면, 이런 솔루션을 Axum으로 표현하는 작업은 매우 직관적이고 쉬울 것입니다. 그래서 프로그래머들은 매우 흔히 발생하는 동시성과 관련된 버그를 피할 수 있게 되는 것이죠.


즉, 병렬프로그래밍을 지원하기 위한 새로운 DSL이라고 생각하면 될 것 같기도 하군요. Axum은 C#과 비슷한 점이 많기도 하고 틀린점도 있는데 대강정리해보면 아래와 같습니다.

-C#과 Axum이 가진 공통점은 :
      모든 C# 3.0의 람다와 LINQ쿼리 같은 표현식들
      모든 C# 3.0의 yield와 yield break같은 구문들
      메서드와 필드 정의들
      델리게이트와 이뉴머레이션 타입들 

-Axum에서 볼 수 없는 C#의 요소들
      클래스, 인터페이스와 구조체
      연산자 정의들
      프로퍼티
      상수 필드와 상수지역변수
      정적 필드와 정적 메서드 

-Axum에서만 볼 수 있는 요소들
      에이전트 와 도메인
      채널
      스키마
      네트워크
      Interleaved control flow


그렇다는 하는 군요. 아무튼, 정리해보면 'Axum은 C#과 비슷한 점도 있고 틀린점도 있으며 병렬프로그래밍을 지원하기 위해서 새롭게 실험적으로 개발되고 있는 DSL이다' 정도가 되려나요?

DSL이라는 말은 제가 붙인겁니다만, 아무튼 모냥을 보니 병렬프로그래밍이라는 부분에 특화된 모습을 보이면서 class정의는 C#, F#, Managed C++, Visual Basic.NET등의 언어를 통해서 하거나 C#을 통해 직접 정의할 수 있다는 걸로 봐서는 DSL이라고 보는게 맞는거 같기도 하군요. 여담이지만 위에서 언급한 4개의 언어의 순서는 제 맘대로 한건 아니구요 문서에 있는 순서를 그대로 언급한 겁니다. F#도 이제 MS내에서도 중요하게 생각하고 있다는 걸까요? 왠지 급흐뭇해 지는 군요.
(찾아보니 이전에 Maestro라는 코드네임으로 개발되던 언어였고 DSL이 맞군요 ㅋ)


여담2 이지만 이런 구절도 있었습니다. "Axum is a .NET language and can use libraries written in other .NET language such as C#, Visual Basic or F#." 이제 F#도 C#과 VB.NET으로 대표되는 주요언어에 포함되는 느낌이로군요 캬캬캬.

아무튼, Axum은 여기서 받으실 수 있습니다. 그리고 그 사이트에서 문서도 보실 수 있구요. 좀 더 자세한 이야기는 다음포스트로 넘기기로 할까요?

-나만 몰랐던가? concurrency와 parallel은 다른 것이다!

일단, 사전적 정의를 보자면 아래과 같습니다.

concurrent - 무언가가 시간적으로 동시에 일어나는 이미지
parallel - 무언가 동일한게 시간&공간적으로 다른곳에 존재하는 이미지

그리고 여기에 대한 좋은 설명이 있어서 참고해봤는데요, 싱글코어 CPU에서 실행되는 두개의 concurrent한 스레드는 concurrent하지만, parallel하지는 않다는 이야기이고... parallel은 멀티코어, 멀티CPU, 분산환경에서 얻을 수 있는 장점이라는 이야기더군요 즉, concurrent하다고 해서, parallel한것은 아니라는 것입니다.

 

- 참고자료

1. Axum Programmer's Guide, Microsoft Corporation
2. AXUM LANGUAGE OVERVIEW, Niklas Gustafsson
3. http://blogs.sun.com/yuanlin/entry/concurrency_vs_parallelism_concurrent_programming