안녕하세요. 이번에 Visual Studio Team System 2010 공식 블로그에 새롭게 참여하게 된 LazyDeveloper.Net의 kkongchi라고 합니다. Better Code 시리즈를 통해서 Code Analysis, Unit Test 등에 대한 포스팅을 해보도록 하겠습니다. 부족한 부분 많이 지적해 주시길 바랍니다.

 

TDD?

eXtreme Programming의 창시자 중 하나인 Kent Beck의 eXtreme Programming explained라는 책을 보면 Test를 작성하는 방법에 대해서 이렇게 기술하고 있습니다.

  • If the interface for a method is at all unclear, you write a test before you write the method. (메서드의 인터페이스가 클리어하지 않다면, 메서드를 작성하기 전에 테스트를 먼저 작성해라)

  • If the interface is clear, but you imagine that the implementation will be the least bit complicated, you write a test before you write the method. (메서드의 인터페이스가 클리어하더라도 당신이 생각하기에 구현이 조금 복잡할 것 같다면, 메서드를 작성하기 전에 먼저 테스트를 작성해라)

  • 이런 eXtreme Programming의 Test-Before-Writing 전략을 개발 프로세스에 전면적으로 도입하는 것을 Test Driven Development, 즉 TDD라고 합니다. TDD에 관한 위키피디아 페이지에서 소개하는 TDD의 개발 사이클은 다음과 같습니다. “Red, Green, Refactor”라고 표현하기도 합니다.

    다들 아시다시피, Visual Studio에서는 2005 버전에서부터 Team System의 일부로써 Testing Framework을 제공하고 지원해왔습니다. 그리고 드디어 이번 Visual Studio Team System 2010에서는 완벽하게 TDD의 개념이 Visual Studio Team System안으로 녹아 들어가게 된 것 같습니다. 바로 새롭게 추가된 기능 “Generate” 기능을 통해서, Test를 먼저 작성한 후에 그 Test로부터 코드를 자동으로 Generate해주는 기능이 추가된 것입니다.

     

    TDD Development in VSTS 2010 by “Generate”

    지난 11월에 나온 Visual Studio 2010 and .NET Framework 4.0 Training Kit의 Lab을 통해서 이 기능에 대해서 좀 더 자세히 알아보도록 하겠습니다.

     

    당연히 먼저 테스트를 작성하는 것부터 시작합니다. 하지만, 아직 만들어지지 않은 클래스이기 때문에 아래 그림처럼 빨간색 물결 라인으로 경고가 뜹니다. 여기서 마우스 오른쪽 버튼을 눌러보면, 새로운 “Generate” 기능을 볼 수가 있습니다.

    Generate class를 선택하면 같은 프로젝트에 Class가 추가됩니다. 하지만 Generate other..를 선택하면 아래와 같은 팝업 윈도우가 나옵니다. 클래스를 만들 수 있는 Wizard 개념이라고 보시면 되겠습니다.

    이 Wizard를 통해서 클래스의 Access 한정자, Type, 그리고 파일을 만들 프로젝트까지 설정을 할 수가 있습니다. 이 과정을 통해서 우리는 완벽하게 Test로부터 시작해서 뼈대 코드를 만들어 낼 수가 있습니다. 아래 그림처럼 말이죠..

    이제 이 자동으로 만들어진 뼈대 코드에 구현을 추가하게 되면 여러분들은 다음과 같이 Test를 통과했다는 기분 좋은 화면을 보실 수 있으실 것입니다.


    위에서 보신 Demo Code의 시연은 http://channel9.msdn.com/shows/10-4/10-4-Episode-5-Code-Focused-in-Visual-Studio-2010/#Page=4 에서 Video로도 감상하실 수 있고, http://www.microsoft.com/downloads/details.aspx?FamilyID=752CB725-969B-4732-A383-ED5740F02E93&displaylang=en 에서 Lab Document와 소스 코드도 얻으실 수 있습니다.
     

    지금까지 보신 것처럼 앞으로 출시될 VSTS 2010에서는 IDE 자체에서 완벽한 TDD 지원 기능이 통합되었습니다. TDD가 만능의 도구는 아닙니다. 하지만, 적어도 개발자가 자신의 코드에 대한 이해도가 통상적인 개발 방법보다는 훨씬 크고 깊을 것이라 기대합니다. 어설픈 문서보다는 잘 만들어진 테스트 코드들이 오히려 실제 구현 코드를 이해하는 데 더 도움이 되는 경우도 많습니다. Visual Studio Team System 2010은 효율적인 Test Driven Development를 가능하게 해주는 최고의 도구가 될 것 같습니다.

    부족한 글 읽어주셔서 감사하고, 많은 의견 부탁 드립니다.

    [C# 4.0] Generic Covariance And Contra Variance

    C# 2009. 4. 13. 20:22 Posted by 알 수 없는 사용자
    처음에 이 용어를 보고 정확하게 무슨 뜻인지 잘 몰랐습니다.
    그래서 이곳 저곳 검색해 본 결과, 좋은 예제를 하나 소개해 드립니다.
    참고 : http://playdotnet.spaces.live.com/blog/cns!7F811570C85CF4EA!4600.entry
    public class Employee { }
    public class Manager:Employee { }
    
    Employee employee = new Employee();
    Manager manager = new Manager();
    //Covariance.
    Employee manager = new Manager(); 
    
    위 예제의 마지막 코드를 보면 Manager 타입의 객체가 Employee 타입의 Manager 변수로 대입 되었습니다. 생각해 보건대, 매니져도 월급을 받는 직원이므로 당연한 것이지만, 프로그래밍 세계에서는 이것을 Covariance 로 부르더군요. 저도 알게 모르게 이런 코드를 많이 사용했었습니다.

    그럼 이건 어떤가요?
    public void GetSalary(Employee employee) { }
    Employee employee = new Employee();
    GetSalary(employee);
    Manager manager = new Manager();
    
    //Contra variance.
    GetSalary(manager);
    
    이번 코드에서는 직원에 월급을 주고 있습니다. 매니져도 직원이므로 월급을 주는 것이 당연합니다. 이런 경우를 Contra Variance라 하네요. 참 재미있는 용어들입니다. 언뜻 생각하면 참 당연한 말인데요. ^^;  
    참 그리고 보니, InVariance 도 있습니다.
    //AppointNewManager() 는 Manager 타입의 변수를 return 합니다.
    Product product = AppointNewManager();
    
    새로운 매니저를 제품으로 볼 수는 없지요. 가끔 그러고 싶은 생각도 있습니다. ㅋㅋㅋ

    C# 버젼 별로 variance의 의미를 종합해 보면은요,

    Variance in Arrays (C# 1.0)

    Value 타입의 Integer 타입의 Array는 당연히 Double Type의 변수를 Element로 사용할 수 없습니다. Invariance 합니다. 
    Int32[] numbers = new Double[3];
     
    Reference 타입의 경우 아래  코드는 Covariance합니다. 단 매니져가 직원이어야 합니다., 쉽게 말하면 매니져의 부모 타입이 Employee 이지요, 근데 가끔 프리랜서도 있을수 있으므로 주의!
    Employee[] employees = new Manager[3];
      
    public class Animal { }
    public class Lion:Animal { }
    Animal[] animals = new Lion[3];
     
    위 예제는 Covariance 하지만, 만약 이런경우에는 
      
    public class Deer Animal }
    Animal[] animals = new Lion[3];
    animals[0] = new Deer();

    동물에 사자도 들어 갈수 있고, 사슴도 가능하지만(Covariance), 실제 코드에서는 문제가 발생할 수 있습니다.  animals array 가 사자 우리라고 생각한다면, 들어간 사슴은 잡아 먹히겠지요. T.T

    Variance in Delegate-Member Association (C# 2.0)
     
    Func<Employee> generateEmployee = AppointNewManager;
    Action<Manager> salaryAction = GetSalary;
     
    Delegate Func<T> 는 인자는 없고, return type은 타입 T입니다. 
    AppointNewManager는 Manager 타입을 return 하고 Manager 타입의 부모는  당연히 employee입니다. 즉 Covariance 합니다
     
    Delegate Action<T> 는 타입 T의 변수를 인자로 받고, return 값은 없습니다.
    GetSalary는 Manager 타입의 변수를 인자로 받는데, 이것 역시 매니져는 직원이므로 월급을 받을 수 있고, 아까 전에 언급한대로 Contra Variance라 부릅니다.

    Variance in Generic Delegate (C# 3.0)
     
    Func<Manager> generateManager = AppointNewManager;
    Func<Employee> generateEmployee = genrateManager;

    Action<Employee> salaryAction = GetSalary;
    Action<Manager> salary = salaryAction;
     
    C# 2.0 예제와는 달리 이 예제들은 Invariance 합니다. Generic delegate에 대해서는 compile error가 발생합니다. Generic 의 업격한 타입 검사가 이런 문제는 발생시키는 건가요? 
    C# 4.0 에서는 이런 문제를 해결하기 위해 Generic Covariance And Contra Variance 가 등장합니다.

    Variance for Generic Delegates (C# 4.0)

    Covariance 를 지원하려면. OUT 
    public delegate Func1<out T>();
     
    Func1<Manager> generateManager = AppointNewManager;
    Func1<Employee> generateEmployee = generateManager;
     
    Contra Variance 의 경우는 IN
    public delegate void Action1<in T>(T a);
    Action1<Employee> salaryAction = GetSalary;
    Action1<Manager> salary = salaryAction;

    약 처음부터 이 부분을 보셨다면, C#에 익숙하지 않은 저 같은 사람은 이해 하기 가 많이 어려웠을겁니다. 그래서 공부하면서 정리한 내용과 함꼐,  가장 쉽다고 생각한 블로그에서 인용 한 것인데,  제가 잘 이해했는지 모르겠네요.  말로 설명하는 것 보다, 하나의 구체적인 예를 들고 적용해 보면 더 확실히 의미가 다가올 것 같습니다. 제 노트북에서는 Virtual PC 돌아가는 것도 상당히 버거워서 실제 컴파일은 해 보지도 못 했답니다. 양해부탁드립니다. 





    'C#' 카테고리의 다른 글

    Welcome to Dynamic C#(2) - Wanna be a polyglot.  (2) 2009.05.17
    Welcome to Dynamic C#(1) - 첫만남.  (1) 2009.05.04
    [C# 4.0] New Extension Method “Zip”  (1) 2009.04.08
    [C# 4.0] Duck Typing  (6) 2009.04.06
    [C# 4.0] Named and Optional Parameters  (1) 2009.04.06

    [MEF] 6. Lazy Exports

    Managed Extensibility Framework 2009. 4. 13. 00:38 Posted by POWERUMC
    일반적인 Exports
     
    Composable Part 를 구성하는 동안 특정 Part 에 대한 요청으로 객체 내부의 객체가 필요할 때가 있습니다. 만약 객체가 이런 연관 관계가 있을 경우 객체 내부에 ImportAttribute 을 선언하여 외부 Part 를 Import 할 수 있습니다. 이런 경우는 객체 내부에 Export 간의 Related 관계를 갖게 됨으로써 자동적으로 객체를 초기화할 수 있게 됩니다. ([MEF] 3. Export 선언 참조)
     
    일반적인 Export 를 통해 객체 내부에 Import 를 선언하는 방법입니다.
     
    class Program
    {
            static void Main(string[] args)
            {
                   Program p = new Program();
                   p.Run();
            }
     
            void Run()
            {
                   var catalog = new AggregateCatalog(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
     
                   var container = new CompositionContainer(catalog);
                   var batch = new CompositionBatch();
                   batch.AddPart(this);
     
                   container.Compose(batch);
     
                   var obj = container.GetExportedObject<EmailMessageSender>();
                   obj.Sender.Say();
            }
    }
     
    [Export]
    public class MessageSender
    {
            public void Say()
            {
                   Console.WriteLine("Say Method");
            }
    }
     
    [Export]
    public class EmailMessageSender
    {
            [Import]
            public MessageSender Sender { get; set; }
    }
     
     
    Lazy Exports
     
    하지만 비용이 비싼 객체를 생성할 경우 위의 [일반적인 Exports] 는 매우 비효율적일 수 있습니다. 객체 내부의 Import Object 를 사용하지 않을 가능성이 크거나, 객체의 생성 비용이 클 경우는 Lazy Export 를 고려해야 합니다. 그리고 내부 객체가 동기적(Synchronicity)이 아닌 비동기성(Asynchronism) 성격의 객체일 경우에도 반드시 필요한 기법입니다.
     
    이런 경우 내부 객체의 생성을 선택적, 수동적으로 제어하여, 게으른 초기화(Lazy Initialization) 를 할 필요가 있습니다.
     
    아래의 굵은 표시의 코드가 Lazy Export 로 제어하는 코드입니다.
     
    class Program
    {
            static void Main(string[] args)
            {
                   Program p = new Program();
                   p.Run();
            }
     
            void Run()
            {
                   var catalog = new AggregateCatalog(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
     
                   var container = new CompositionContainer(catalog);
                   var batch = new CompositionBatch();
                   batch.AddPart(this);
     
                   container.Compose(batch);
     
                   var obj = container.GetExportedObject<EmailMessageSender>();
                   obj.Sender.Say();
     
                   var lazyObj = container.GetExportedObject<EmailMessageSenderByLazyExport>();
                   lazyObj.Sender.GetExportedObject().Say();
            }
    }
     
    [Export]
    public class MessageSender
    {
            public void Say()
            {
                   Console.WriteLine("Say Method");
            }
    }
     
    [Export]
    public class EmailMessageSender
    {
            [Import]
            public MessageSender Sender { get; set; }
    }
     
    [Export]
    public class EmailMessageSenderByLazyExport
    {
            [Import]
            public Export<MessageSender> Sender { get; set; }
    }
     
    ImportAttribute 의 프로퍼티를 Export<T> 타입으로 변경하면 내부 객체를 GetExportedObject() 메서드를 이용하여 지연하여 객체를 생성할 수 있습니다.

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

    [MEF] 8. Strongly Typed Metadata  (0) 2009.04.16
    [MEF] 7. Exports and Metadata  (0) 2009.04.16
    [MEF] 5. Catalog 사용  (0) 2009.04.09
    [MEF] 4. Import 선언  (0) 2009.04.07
    [MEF] 3. Export 선언  (0) 2009.03.29

    [Blueprints] S+S Blueprints

    VIsual Studio Extensibility 2009. 4. 12. 23:13 Posted by POWERUMC
    새로운 트랜드 Blueprints
     
    Blueprints 는 새로운 개념의 Software Factory 입니다. 언제나 우리는 반복되는 작업과 그것을 수행하기 위한 새로운 기술, 그리고 좋은 패키지를 만들기 위한 디자인, 그리고 버그를 수정하기 위한 작업을 팩토리(Factory) 라는 개념의 트랜드된 기술입니다. 팩토리(Factory) 는 Web Service, Rich Internet Application(RIA), Service Facade 를 쉽게 제공할 수 있으며 그것은 특정 프로세스, 리소스, 가이드라인, 패턴, 템플릿, 라이브러리 등이 포함됩니다.
     
    Blueprints 의 팩토리는 소프트웨어 생산 공정(Software product line-SPL) 의 형태입니다. 일관된 공통적인 프로세스를 통해 패턴을 정하여 또는 공통적인 프로세스를 정의함으로써 재사용성을 높이고 체계적인 생산 공정을 정의할 수 있습니다.
     
    Software Factory 는 특정 도메인 언어(Domain-Specific Language-DSLs) 를 통해 모델 기반 개발(Model-driven Development-MDD) 를 중요시하는 마이크로소프트 플랫폼을 위한 SPLs 입니다. MDD 는 Application, Services, Layers, Component 등의 복잡한 요소를 대상으로 하는데, Software Factory 는 이러한 복잡한 요소들을 단순화할 수 있습니다.
     
    [그림1] Software Factory 가 생성되고 적용되는 그림
     
     
    Blueprints 가 있기 까지
     
    Blueprints 는 Guidance Automation Toolkit(GAT) 가 그 기반에 존재합니다. GAT 는 Microsoft 의 Pattern & Practice 팀에서 Guidance Automation(GA) 를 쉽게 적용하기 위한 툴입니다. GAT 는 Guidance Automation Extension(GAX) 를 기반으로 Web Service, Web Client, Smart Client 등 Enterprise Library 와 통합시켰고 Guidance Cunsumer 를 통해 커스터마이징이 가능한 도구입니다.
     
    하지만 GAT 는 Guidance Automation(GA) 는 한계가 있었고, 이런 GAX/GAT 를 기반으로 RSS-based Factory 와 런타임 확장 및 업데이트가 가능한 새로운 서비스를 제공하게 되었습니다. 바로 이것이 S+S Blueprints 입니다.
     
    S+S 는 Software plus Services 라는 의미로 Web 2.0 과 SOA 양측 모두 적용할 수 있습니다. Web 2.0 은 나은 응답성을 요구하고 SOA 는 보안과 안정성을 요구하는데, 기업은 이런 SOA 에 Web 2.0 의 응답성과 유연함의 장점을 원합니다. 이러한 Server Software base 의 IT System 은 SaaS Base 의 Web 2.0 을 지원하기 위해 Loosely connected message-passing system 의 서비스를 추가할 것입니다. 기업은 이러한 데이터 보안, 가용성, 응답성과 유연함을 원할 것입니다.
     
    그리고 DSL Tools 입니다. DSL Tools 은 Visual Studio 2005 이상, Team Architect 버전에 포함된 Domain-Specific Language 를 쉽게 구현하기 위한 도구입니다. DSL 은 저렴한 비용으로 UML Modeling 을 할 수 있으며, 기업의 이해관계가 다른 (예를 들어 기업의 경영진과 실무진??) 사람과 통용할 수 있는 좋은 도구가 됩니다.
     
    [그림2] 오늘날 Factory 기술의 발전
     
     
    Blueprints 다운로드 받기
     
    Blueprints 는 Codeplex 에서 다운로드 할 수 있습니다. 현재 Blueprints 는 November CTP Refresh 2.1.2 버전입니다.
     
    Blueprints Download
     
     
    Blueprints 는 Visual Studio Extensibility(VSX) 로 제작되어 Visual Studio 에 Blueprints Manager(BPM) 를 통해 실행할 수 있습니다.
     
    [그림3] Blueprints Manager(BPM) 실행 화면
     
     
    오늘은 Blueprints 를 소개하는 단원에서 끝내며, 추후에 Blueprints 의 Factory 를 만들고 Publish, 그리고 프로세스의 Work flow 등 보다 근접한 S+S Blueprints 를 소개해 드리도록 하겠습니다.
     
    참고 문헌
     
     

    Welcome to F#(3) - 사소한 탐색전.

    F# 2009. 4. 12. 22:10 Posted by 알 수 없는 사용자

    -관심있으면 많이 알아봐야 하는 법.
    이제 F#과의 만남도 어느덧 세번째에 접어들었네요. 한 두번쯤 만나면 상대방에 대해 관심이 있는지 없는지 스스로 눈치챌 수 있겠죠. 그리고 관심이 있다면, 더 열심히 상대방에 대해서 알려고 노력하고 있을테구요. F#에 대해서 알려고 노력하다보니, F#의 4차원적인 면을 하나발견하고 잠깐 당황해서 허우적댔습니다. 거기에 대해서 짧게 적어보려 합니다.

    -짧은 예제를 통해 까발려본 F#의 4차원적 특징

    #light
    
    type TwoNumbers =
        {Number1 : int; Number2 : int}
    
    let num = {Number1 = 3; Number2 = 5}
    
    printfn "%d %d" num.Number1 num.Number2
    

    그리고 실행해보면 아래와 같은 결과가 나온다.


    음~ 예상했던 대로 결과가 잘 나왔습니다. 그런데 왠지 타입선언과 그 타입을 실행하는 코드는 다른 소스파일에 넣는게 맞는거 같아서 타입선언을 TwoNumbers라는 파일을 생성해서 거기에 넣자는 생각이 들었죠. 그래서 C#에서 하던것 처럼 새로운 파일을 생성해서 거기에 타입선언 코드를 집어넣고, 다시 자신있게 컴파일을 실행했습니다. 그런데! 다음과 같은 오류가 발생하더군요.

    오류 1 - The record label 'Number1' is not defined.

    오류 2 - Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved

    오류 3 - Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved



    즉, Number1이랑 Number2가 선언되어 있는 타입을 찾을 수 없다는 말인데요. 이게 무슨 소리입니까;; 같은 솔루션에 있는 파일에 클래스의 선언을 옮겼는데 못 찾다니요..? 그런데, VisualStudio의 한지붕아래에서 살아서 전혀 눈치를 못채고 있었는데, F#의 솔루션 탐색기에는 다른 언어들과는 다른 뭔가 특별한게 있더군요. 이런 4차원 F#!!!

    바로 위 그림에서 볼 수 있는 Move Up, Move Down, Add Above, Add Below말인거죠. 무슨 아이돌 그룹이라도 되는 마냥 4인조가 나란히 모여있죠. 이건 당췌 뭘까요? 아! 혹시 F#은 위에서 부터 아래로 차례대로 파일들을 컴파일 하는걸까요? 그럼 타입선언이 있는 TwoNumbers파일을 Move Up해서 다시 컴파일을 해보죠!! 자신있게 컴파일을 했건만 결과는 똑같은 에러가 납니다. 연애를 해봤거나, 작업을 절박하게 걸어본 사람은 그 사람의 성격을 알았다고 생각해서 그에 맞춰주려다가 오히려 더 곤혹스러웠던 상황이 있을겁니다.

    이런. F#은 도대체 왜 이렇게 특이한걸까요? 그래서 F#을 잘아는 사람들에게 정보를 얻어보니, F#은 위에서 부터 차례대로 컴파일을 하는 건 맞는데, 그 파일들이 자동으로 하나의 모듈단위로 컴파일이 되고, 그 모듈을 이용하려면, open을 이용해서 그 모듈의 내용을 열어야 사용이 가능하다는 거 였더군요. 그래서 아래와 같이 모듈의 이름을 open해주었습니다.


    #light
    
    open TwoNumbers
    
    let num = {Number1 = 3; Number2 = 5}
    
    printfn "%d %d" num.Number1 num.Number2
    

    이제 컴파일이 잘 됩니다.>_<! 모듈의 이름은 명시적으로 아래와같이,

    module MyCompany.MyLibrary.MyModule

    (위와 아래의 선언은 동일하다)


    namespace MyCompany.MyLibrary
    module MyModule =
        .......

    이렇게 지정해주지 않는이상 파일이름과 동일하며, 무조건 맨 앞의 문자는 대문자가 됩니다.(즉 파일의 이름이 twoNumbers 였더라도, 모듈의 이름은 TwoNumbers가 된다는 말)

    -그냥 추가로 이야기하는 공간-

    type Card =
        { Number: int; Shape: int }

    이렇게 타입(클래스)를 선언하고, 위 선언을 F# Interactive에서 평가하고 아래와 같은 결과가 나옵니다.

    type Card =
      {Number: int;
       Shape: int;}

    그리고 아래처럼 계속 평가식을 입력해보면....

    > let v = {Number = 3; Shape = 5};;

    val v : Card

    > let a = {a = 4; b = 5};;

      let a = {a = 4; b = 5};;
      ---------^^
    stdin(4,10): error FS0039: The record label 'a' is not defined.

    > v;;
    val it : Card = {Number = 3;
                     Shape = 5;}
    >

    즉, 타입이름을 명시하지 않아도 멤버의 이름과 타입을 보고 알아서 타입을 찾아서 생성한다는 겁니다. 그래서 a와 b라는 멤버로 생성하려고 했을때, 그런 멤버를 가진 타입이 없어서 에러가 발생하는 거죠.


    -어디까지 4차원일까?
    F#은 알면 알수록 4차원인거 같네요. 아... F#에 대해서 더 잘 알게되면 F#의 마음을 얻고 잘 지낼 수 있을까요? 일단 최대한 노력해보는 수 밖엔 없겠군요. 이렇게 짧은 탐색전을 마치겠습니다.

    -참고자료
    1. Expert F#, Don Syme, Adam Granicz, Antonio Cisternino, APRESS.
    2. http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec2.aspx#_Toc207785764

    [MEF] 5. Catalog 사용

    Managed Extensibility Framework 2009. 4. 9. 21:31 Posted by POWERUMC
    Catalog
     
    Catalog 는 동적으로 Composable Part 를 찾아 Container 에 등록합니다. Composable Part 는 ExportAttribute 으로 Contract 를 선언할 수 있는데 개별적으로 일일이 Composable Part 를 등록하는 것은 너무나 큰 반복 작업이 될 수 있지만, MEF 의 Catalog 로 쉽게 자동적으로 등록을 할 수 있습니다.
     
    Catalog 를 사용하지 않는 Composable Part 의 등록는 매우 고단한 작업입니다. 아래의 예제 소스 코드는 수동으로 Composable Part 를 등록하는 방법입니다.
     
     
    예제에서는 단지 하나의 Export 를 등록하였지만 실제로 이러한 Composable Part 는 수십에서 수백개를 넘을 수 도 있습니다. 많은 Composable Part 를 동적이고 또는 자동적으로 등록해 주기 위해서 Catalog 를 사용하면 쉽게 해결할 수 있습니다.
     
     
    이 외에도 Composable Part 를 Catalog 에 등록하는 여러 가지 방법이 있습니다. 아래는 MEF 에서 지원하는 Catalog 입니다.
     
     
    Assembly Catalog
     
    Assembly Catalog 는 닷넷 어셈블리를 Catalog 로 사용할 수 있습니다.
     
    public AssemblyCatalog(string codeBase)
    public AssemblyCatalog(Assembly assembly)
     
    var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
     
    AssemblyCatalog 의 시그너처(Signature) 에서 보듯이 CodeBase 로 Catalog 를 사용할 수 있지만, 실버라이트에서는 CodeBase 를 지원하지 않으므로 실버라이트에서는 CodeBase 로 AssemblyCatalog 를 사용할 수 없습니다.
     
     
    Directory Catalog
     
    Directory Catalog 를 사용하면 특정 폴더의 어셈블리를 모두 검색하여 Composable Part 를 사용할 수 있습니다.
     
    public DirectoryCatalog(string path)
    public DirectoryCatalog(string path, string searchPattern)
     
    Directory Catalog 는 내부적으로 System.IO 의 Directory.GetFiles() 메서드를 사용하여 지정한 폴더의 모든 어셈블리를 검색하도록 하여 Composable Part 를 가져오도록 합니다.
     
    var catalog = new DirectoryCatalog("Addins");
     
    기본적으로 *.DLL 확장자의 어셈블리만 검색하도록 설정되어있고, 어셈블리 파일의 검색 패턴을 지정하여 검색할 수 있습니다.
     
    var catalog = new DirectoryCatalog("Addins", "*.exe");
     
    아마 MEF 의 예제중에 XFileExplorer 처럼 특정 폴더에 어셈블리를 복사해 넣으면 자동으로 Composable Part 가 로드되는 예제가 있는데, 이것은 DirectoryCatalog 가 자동으로 처리해 주는 것이 아니라 FileSystemWatcher 클래스를 이용하여 직접 구현해야 합니다.
     
    FileSystemWatcher 로 파일의 변경이 감지되면 DirectoryCatalog 의 Refresh() 메서드를 이용하여 폴더를 재검색 또는 새로고침을 할 수 있습니다.
     
     
    Aggregation Catalog
     
    Aggregation Catalog 는 복합적인 Catalog 를 사용할 수 있도록 합니다. 만약 Assembly Catalog 와 Directory Catalog 등을 동시에 사용하여 Composable Part 를 가져오도록 하려면 Aggregation Catalog 를 사용하면 됩니다.
     
    public AggregateCatalog(params ComposablePartCatalog[] catalogs)
     
    Aggregation Catalog 의 생성자는 params 로 인자를 받을 수 있습니다.
     
    var catalog = new AggregateCatalog(   new AssemblyCatalog(Assembly.GetExecutingAssembly()),
                                                                                new DirectoryCatalog("."));
     
     
    Type Catalog
     
    Type Catalog 는 Composable Part 를 Type 으로 개별적으로 사용하도록 합니다. 가장 단순하고 무식(?)한 방법일 수도 있지만 세세한 제어가 필요할 때 사용 가능한 Catalog 일 것 같습니다.
     
    public TypeCatalog(params Type[] types)
    public TypeCatalog(IEnumerable<Type> types)
     
    var catalog = new TypeCatalog(typeof(EMailMessageSender), typeof(PhoneMessageSender));
     
     
    Using catalog with a Container
     
    이제 Catalog 를 Composable Container 에서 Composition 하도록 넘겨주는 일만 남았습니다.
     
    public CompositionContainer()
    public CompositionContainer(params ExportProvider[] providers)
    public CompositionContainer(ComposablePartCatalog catalog, params ExportProvider[] providers)
     
    var container = new CompositionContainer(catalog);
     

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

    [MEF] 7. Exports and Metadata  (0) 2009.04.16
    [MEF] 6. Lazy Exports  (0) 2009.04.13
    [MEF] 4. Import 선언  (0) 2009.04.07
    [MEF] 3. Export 선언  (0) 2009.03.29
    [MEF] 2. Parts 와 Contracts 선언  (0) 2009.03.22

    WPF 4의 향상된 기능과 Windows 7 지원

    WPF 2009. 4. 9. 02:33 Posted by 알 수 없는 사용자

    WPF가 발표된지도 많은 시간이 흘렀지만 아직 WPF를 사용한 어플리케이션이 많이 나오지 않는 것이 현실입니다. 앞으로 Visual Studio 2010과 .NET Framework 4.0이 발표되면 WPF 역시 4.0으로 버전업이 되는데 이제 현실적으로 많이 사용 될 수 있을 정도로 많은 발전이 있습니다. 

    알려진 바와 같이 Visual Studio 2010 IDE에서도 WPF가 사용될 정도로 성능이나 여러 면에서 많은 발전이 있습니다.


    이번 MIX09 행사의 WPF4 소개 세션 자료를 보면 매우 많은 요소가 향상된 것을 볼 수 있습니다.

    이 중에서 가장 눈에 띄는 것은 아무래도 Multi-Touch 지원이 되겠는데 이 것은 Windows 7에서 기본으로 Multi-Touch를 지원 하게 됨으로써 WPF에서도 이를 활용한 어플리케이션 개발을 할 수 있게 되었습니다.

     

    이 외에도 중요한 몇 가지를 보면 Windows 7에서 새롭게 바뀐 Taskbar와 Office 2007에서 사용된 Ribbon UI를 기본으로 지원하게 되고 다양한 새로운 컨트롤과 .NET Framework 4에서 향상된 언어 기능들도 추가 되었습니다. 

    이런 향상된 기능들을 지원하기 위해 WPF에서 어떤 변화가 있는지 자세히 알아보도록 하겠습니다. 


    Multi-Touch in WPF

     

    UIElement 변화 

    WPF 개발을 해보신 분들은 UIElement 클래스에 대해 잘 알고 계실겁니다. UIElement 클래스는 WPF의 가장 기본이 되는 최상위 기본 클래스인데 멀티터치 지원을 위해서 내부적으로 몇 가지 변화가 생겼습니다. 우선 기존의 이벤트로는 멀티 터치를 지원 할 수 없기 때문에 멀티터치와 제스처 인식을 위한 이벤트가 추가 되었습니다.

     

    멀티터치 지원 컨트롤 

    ScrollViewer 컨트롤의 경우 제스처 인식을 하도록 업데이트 되었고 다른 기본 컨트롤들도 멀티터치 지원을 위해 업데이트 되었습니다. 동시에 하나 이상의 포인트를 인식하기 위해 멀티캡쳐 기능도 지원하게 되었습니다. 이 외에도 ScatterView 같은 멀티터치를 위한 새로운 컨트롤도 추가 되었습니다.

     

    Surface SDK 2.0 호환 

    Sufrace SDK 2.0의 호환으로 Surface 컴퓨터의 멀티터치 어플리케이션 개발을 쉽게 할 수 있습니다.

    WPF Taskbar Integration

     

    Windows 7에서는 기존보다 향상된 태스크바를 제공하는데 이를 지원하기 위한 내용이 포함 되었습니다.

     

    Windows API Code Pack for .NET

    Windows 7에서 추가되거나 향상된 API들을 사용하기 위해서는 C, C++, COM API 같은 네이티브 코드를 사용해야 합니다. 그러나 C# 등의 매니지드 코드를 사용하는 닷넷 개발자에게는 이것이 어렵게 느껴 질 수 있습니다. 그렇다고 새로운 멋진 기능들을 포기하자니 아쉽고 네이티브 코드를 사용하자니 불편하고 좀 더 편하게 할 수 있는 방법은 없을까요?  

    이러한 것을 해결 하기 위해 Microsoft에서는  Windows Vista Bridge project를 만들었는데 이것을 사용하면 매니지드 코드 개발자가 Windows API를 쉽게 사용 할 수 있습니다. 현재 최신 버전은 1.4인데 Restart and Recovery, Search, Power Awareness and other Shell integrations 같은 Windows Vista의 많은 유용한 기능들을 포함 하고 있습니다. 그러나 현재 버전은 Windows7의 기능들을 포함하고 있지는 않습니다. 

    Windows7은 현재 베타가 공개되었고 조만간 RC버전이 나온다고 하는데 Windows 7의 API 지원을 위한  Windows API Code Pack for the .NET Library(이것은 Windows Vista Bridge의 새 이름)도 함께 개발중으로 같이 배포 될 예정입니다. 

    현재는 Windows Vista Bridge에서 약간 수정된 버전으로 Windows 7 API 일부를 지원하는 샘플 라이브러리가 있는데 이것은 다음에 자세히 알아 보도록 하겠습니다. 

     

    WPF Ribbon

    Visual Studio 2008에서는 MFC를 사용하여 Ribbon UI를 개발 할 수 있습니다. 그런데 WPF에서는 기본적으로는 Ribbon UI를 지원하지 못하고 WPF Toolkit을 통해서 따로 지원하고 있는데 WPF 4에서는 Ribbon UI를 기본적으로 지원하게 됩니다. 

     

    WPF Controls

    윈도우 프로젝트에서 많이 쓰이는 컨트롤 중 하나가 데이터 그리드나 달력 컨트롤 등이 있는데 WPF 기본 컨트롤에서는 지원하지 않고 WPF Toolkit으로 따로 지원하고 있습니다. Ribbon과 마찬가지로 이것도 역시 WPF 4에서는 기본으로 포함되게 됩니다. 이 외에도 Silverlight에서 지원하고 있는 차트 컨트롤 등도 WPF에서 역시 지원하게 됩니다.


     

    대표적으로 살펴 본 것 외에도 많은 변화가 있고 향상 되었습니다. 다음 포스팅 부터는 이번에 살펴본 것을 중심으로 실제로 어떻게 사용하고 구현하게 되는지 자세히 알아보도록 하겠습니다. 

    앞으로 Visual Studio 2010과 WPF 4의 향상된 기능 많이 기대 해주세요 :)

    'WPF' 카테고리의 다른 글

    WPF 리본 컨트롤 RTW 출시  (4) 2010.08.05
    WPF Features Preview (3) - Styling the DataGrid  (1) 2009.04.23
    WPF Features Preview (2) – DatePicker  (1) 2009.04.22
    WPF Features Preview (1) – DataGrid  (1) 2009.04.17

    Welcome to F#(2) - 두번째 만남.

    F# 2009. 4. 8. 23:40 Posted by 알 수 없는 사용자

    -애프터
    첫번째 만남이 끝난뒤에, 어떻게 애프터를 이어나가야 할지 무처이나 고민했습니다. 첫만남이야 가볍게 서로의 얼굴도 보고, 성격도 맛보는 정도에서 끝난다지만 애프터에서는 서로에 대해서 천천히 자세히 알아가야 할텐데, 갑자기 참여중인 프로젝트의 상황이 악화되서 시간이 잘 나지 않고, 이해부족과 실력부족이 겹쳐서 어떻게 글을 계속 써나가야할지 고민이 많았습니다. 그러다가 직장동료에게 물어봤습니다.

    "만약에 튜토리얼을 쓴다면, 어떻게 쓰는게 좋을까?"
    "글쎄, 나는 그런게 좋던데. 왜 작은 예제에서 시작해서 하나씩 추가되어 가면서 설명해주는 그런거 있잖아."

    이거다 싶었습니다. 그래서 제 내공이 받쳐줄지는 모르겠지만, 최대한 예제를 통해서 F#과의 애프터를 진행해볼까 합니다. 언제나 그렇듯이 제 글에 어색하거나 잘못된 내용이 있을수 있으니 언제나 따뜻한 피드백으로 격려해주시기 바랍니다.(말씀드렸듯이 차가운 피드백은 바로 반사-_-) 그럼 일단 애프터 장소로 가서 F#을 좀 더 만나보도록 하죠~.

    -F#에서는 타입을 안쓰는거 같더라?
    일단 F#에서 타입을 결정하는데 쓰이는 타입유추(Type Inference)에 대해서 알아보겠습니다. 타입유추는 F#에서만 쓰이는 개념은 아닙니다만, 저 같이 함수형언어에 친숙하지 않은 경우에는 생소함을 느끼게 됩니다. 우선 아래와 같은 예제를 작성해서 아래 두줄을 드래그 해서 F# Interactive로 보내보죠. F# Interactive를 띄우는 방법과 F# Interactive로 보내는 방법은 잊지 않으셨죠? 잊으셨다면, 이전 포스트를 참조해주세요~.

    #light

    let count = 1
    printfn "%d" count


    실행결과에 대해서 이야기 하기전에 #light에 대한 설명을 조금 드리자면, 지난 포스트에서 말씀드린 것 같이 이 지시어는 F#에서 좀더 간략한 문법을 사용할 수 있도록 해줍니다. 그런데, 이런 키워드를 명시적으로 꼭 선언해야 하는 이유는 다음과 같습니다. F#은 OCaml으로 부터 영감을 받아서 설계되고 핵심적인 부분중에 일부분을 공유하고 있씁니다. 그리고 OCaml의 코드를 컴파일할 수 있는 기능을 갖추고 있는데, 간단한 OCaml코드의 경우는 수정없이 컴파일 가능하게 되어있습니다. 그래서 그 경우를 위해서 #light라고 명시해줘야만 F#의 간단한 문법이 적용되는 것입니다.

    그러면, 다시 소스코드로 넘어가서 그 소스의 결과는 아래와 같습니다.

    val count : int
    1
     
    즉, 한줄씩 평가 돼서 그 결과가 나오는 건데요, 첫번째 줄은 count라는 value를 선언했고 그 타입은 int라는 말입니다. 그리고 그 다음줄은 count의 값을 출력한 결과인거죠. 눈치 빠른 분이라면, 아마 여기서 뭔가를 눈치채셨을 겁니다. 타입을 정해주지 않았는데, count의 타입이 int라는걸 문맥을 통해 유추해냈습니다. 그리고 아래의 printfn의 출력패턴을 보면 "%d", 즉 C와 동일하게 정수형값을 출력하겠다는 말인데요, 앞의 평가식에서 count가 정수형이라는 걸 유추해냈기 때문에 에러없이 1을 출력하고 프로그램을 종료합니다. 이런걸 타입 유추라고 부릅니다.(원문으로는 Type Inference인데, inference에 대한 딱히 다른 용어를 찾지 못해서 일단 유추라고 하겠습니다.-_-)

    타입유추는 코드를 분석해서 제약사항들을 모아서 이루어집니다. 여기서 제약사항이란, 매개변수가 가질 수 있는 타입을 명시해줌으로써 제약을 가하는 개념인데요, 문맥에서 타입을 유추할때 +,-,*,/같은 경우는 기본적으로 매개변수를 int타입으로 유추됩니다. 그리고 아래의 예제들을 F# Interative에 평가해보죠.

    let printInt x = printfn "%d" x

    let printString x = printfn "%s" x

    그러면, 아래와 같은 결과가 나오죠.

    val printInt : int -> unit

    val printString : string -> unit

    즉, 문맥상 정수형을 출력하니까 x는 int형이 된거고, 문맥상 스트링을 출력하니깐 x는 스트링으로 유추된 거죠. 그리고 아래의 예제를 더 보시죠.(그리고 참고로 unit은 많은 분들이 기대하시는 것 처럼 unsigned int는 아니구요, 정확하게 같진 않지만 void를 나타내는 F#의 타입입니다.-_-)

    let plusplus x = (x + x)
    let plusplus2Times (x) = plusplus x + plusplus x
    -----결과----
    val plusplus : int -> int
    val plusplus2Times : int -> int

    그리고 아래와 같이 바꿔서 다시 평가해보죠.

    let plusplus x = (x + x)
    let plusplus2Times (x:float) = plusplus x + plusplus x
    -----결과----
    val plusplus : float -> float
    val plusplus2Times : float -> float

    역시 사용되는 문액에 따라 plusplus를 호출하는 plusplus2Times에서 int형 x를 넘겨주면, plusplus의 매개변수도 int타입이 되고, float을 사용하겠다고 타입에 제약을 정해주면(즉, 매개변수 x가 될 수 있는 타입에 명시적으로 제약을 주는 것) 그에 따라서 plusplus에 넘어가는 매개변수와 리턴타입역시 그에 따라 float타입으로 유추되는 것을 볼 수 있죠. 즉, F#에서는 타입을 명시해줄 수도 있지만, 이런 작업을 직접 해주지 않으면 기본적으로는 타입유추를 통해 타입을 알아내고 적용한다는 겁니다.

    -타입유추라는거 왠지 불안해보이는데?
    이런 생각을 해볼 수 있습니다. '과연 이렇게 컴파일러가 타입을 추측해주는게 무슨 장점이 있는거냐?' 이 포스트에서 관련된 내용을 많이 찾아볼 수 있었습니다. 저자는 타입유추의 광팬이로군요. 언제든지 C#같은 언어에서 제공하는 var타입이나 익명메서드등을 사용해서 자기 대신 컴파일러가 타입에 대한 문제를 다루도록 한답니다. 즉, '타입유추는 타입안정성을 해치지 않고 그저 컴파일러가 대신 타입을 찾을뿐이다', '타입을 일일이 적지 안아도 되니깐 리팩토링시에도 편리하다', '타이핑을 줄일 수 있다'랍니다. 그리고 반론도 만만치 않습니다. 아주 긴 댓글로 서로 의견을 주고 받고 있군요. 즉, 한마디로 좋다 나쁘다를 정할 수 없는 취향의 문제인것 같기도 합니다.(우주 끝날때까지도 결론이 안 날문제들이 바로 취향에 관련된 문제죠-_-)

    -F#은 어떤 타입이야?
    그리고 타입이야기가 어쩌다 새어나왔으니, 타입을 한번 적어보겠습니다.
     타입  예  설명
     int  int  그냥 32비트 정수입니다.
     type option  int option, option<int>  선언된 타입의 값이 있거나, 혹은 값이 없는 걸 의미하는 None을 가집니다. Optional parameter와 비슷한 개념입니다.
     type list  int list, list<int>  선언된 타입의 immutable한 값들의 linked list입니다. 리스트의 각 값들은 [5;2;88]처럼 같은 타입을 가져야 합니다.
     type1 -> type2  int -> string  함수타입입니다. 즉, type1을 받아서 결과값으로 type2를 리턴한다는 거죠.
     type1 * ... * typeN  int * string  한쌍(a pair), 두쌍 그리고 그 이상의 타입들의 조합이 가능한 튜플타입입니다. (1, "3")같은 경우 말이죠.
     type []  int[]  배열타입이죠. 1차원이고, 고정된 크기의 mutable한 값들의 모음입니다.
     unit  unit  하나의 값을 나타내는 ()을 나타내는데, 명령형 언어의 void와 비슷한 의미입니다.
     'a, 'b  'a, 'b, 'Key, 'Value  제네릭하게 어떤 타입이든지 올 수 있는 변수타입입니다.

    Expert F#에 나오는 예제를 마지막으로 보겠습니다.

     String.split [' '] "hello world"

     String.split ['a';'e';'i';'o';'u'] "hello world"

    일단 위의 코드를 F# Interactive에 보내서 평가해보면 "The value, constructor, namespace or type 'split' is not defined. A construct with this name was found in FSharp.PowerPack.dll,......"이런 에러가 뜹니다. 즉, String클래스에 split이라는 값이나, 생성자, 네임스페이스 혹은 타입이 존재하지 않는데, FSharp.PowerPack.dll에서 발견이 되었다는 친절한 메세지 입니다. CTP버전으로 오면서 많은 기능이 FSharp.PowerPack.dll로 옮겨졌기 때문입니다. String은 Microsoft.FSharp.Core.String을 참조하는데요 Microsoft.FSharp안에 있는 Core,Collection,Text,String같은 네임스페이스는 String.split이나 open String같이 한 단어로 참조가 가능하고 합니다. 이럴땐, FSharp.PowerPack을 참조추가해줘야겠죠. 참조추가후에 open 지시어를 통해서 해당 네임스페이스의 내용을 알아내야 하는데, F# Code에선 기본적인 Core나, Operators, Collections같은 네임스페이스는 암시적으로 open을 한다고 합니다. 그리고 비주얼 스튜디오가 아닌 F# Interactive에서 참조추가를 하려면, 아래 처럼하면 됩니다.

     > #r "FSharp.PowerPack.dll";;

    --> Referenced 'C:\Program Files\FSharp-1.9.6.2\bin\FSharp.PowerPack.dll'


    그리고 다시 F# Interactive로 보내서 평가해보면 아래와 같은 결과나 나옵니다.

     val it : string list = ["hello"; "world"]
    >
    val it : string list = ["h"; "ll"; " w"; "rld"]

    이 예제에서 ' ', 'a'는 그냥 문자고, "hello world"같은건 문자열, ['a';'e';'i';'o';'u']는 문자의 리스트, ["hello"; "world"]는 문자열의 리스트라는 걸 알 수 있습니다.

    -애프터의 만족도는?
    변명이지만, 시간도 조금은 부족했고, 아는것도 부족하다보니 포스트의 내용이 썩 만족스럽지는 못한 것 같습니다. 애프터가 만족스럽지 못하셨다면, 제탓이 가장크겠군요-_-. 그래도 마음에 드신분이 있다면, 몇번 애프터를 더 해보고 손이라도 잡아봐야 겠죠. 다음번엔 이어서 기본적인 타입에 대해서 좀 더 알아보고, .NET공원에서 놀이기구를 몇개 타보는 걸로 해볼 생각입니다. 그리고 이번포스트에서 제대로 조사하지 못한 부분역시 조사해볼 생각입니다. 데이트장소는 고전적이긴 하지만 놀이공원도 괜찮죠. 그럼 도움이 되는 분들이 있길 바라면서 다음 포스트에서 뵙겠습니다.

    -참고자료
    1. Expert F#, Don Syme, Adam Granicz, Antonio Cisternino, APRESS.
    2. http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec2.aspx#_Toc207785764
    3. http://blogs.msdn.com/jaredpar/archive/2008/09/09/when-to-use-type-inference.aspx

    Visual Studio 2010 & .NET 4.0 참고 자료들

    Visual Studio 2010 2009. 4. 8. 16:37 Posted by 알 수 없는 사용자

    안녕하세요.
    아직 VSTS 2010 관련 한글 자료가 많지 않아 미리 보고 써보는게 쉽지는 않은 상황 입니다.
    그렇다고 계속 기다릴 수도 없고, 비록 영문 자료지만, 충분히 보고 따라 할 수 있는 자료를 소개 합니다.

    마이크로소프트의 개발자 동영상 사이트 중 절때 빠질 수 없는 채널9(Channel9)의 "Visual Studio Team System 2010 Week on Channel 9!" 시리즈가 있습니다.
    여기에서 VSTS 2010의 개발 철학이나 개선되거나 추가된 기능 등에 대한 인터뷰를 볼 수 있습니다.
    사실 영어가 좀 부담이 되는 부분이기는 합니다.

    다음으로 좀 더 볼게 많은 "Visual Studio 2010 and the .NET Framework 4.0 Week!" 시리즈가 있습니다. VSTS 2010 오버뷰 부터 C# 4.0, C++ 10 등 보다 풍부한 볼거리를 제공합니다.

    특히 C#의 아버지인 Anders Hejlsberg의 "C# 4.0 - Questions and reasons behind the answers"는 강력 추천 입니다.

    그리고 마지막으로 Visual Studio 10과 .NET 4.0의 주요 내용을 에피소드로 소개하는 10-4가 있습니다.
    계속 시리즈로 올라오고 있으니 꼭 참고 하시기 바랍니다. 좋은 내용들이 많이 있습니다.

    감사합니다.



     

    [C# 4.0] New Extension Method “Zip”

    C# 2009. 4. 8. 16:10 Posted by 알 수 없는 사용자

    참고 : http://blogs.msdn.com/wriju/archive/2009/02/28/c-4-0-new-extension-method-zip.aspx

    저는 이 방법을 알기 전에 다음과 같은 방법을 사용 했었지요.

    Web 서버에 Post 방식으로 요청을 보낼때 Query String을 사용하게 되었는데, 그 형식은 다음과 같았습니다. 
    custom_action_id=1&id=330&resource_type=lot&uuid=b657895
    parameter 값은 각각 Key 와  Value로 구성되어 있었습니다. 그래서 위와 같은 query string을 자동으로 계산하는 방법을 생각해 보게 되었는데요...

    Select 를 이용해서 원하는 구문을 얻을 수 있었지요.  사실 linq에 익숙해지기 위해 만들어 보았을 뿐 복잡하게 할 필요는 없었습니다.

    근데 C# 4.0 에서 소개된 Zip 메소드를 이용해서 다른 방법으로 바꿔 볼 수 있었습니다.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                string[] parms = { "custom_action_id", "id", "resource_type", "uuid" };
                string[] values = { "1", "330", "Lot", "b53c37ed8c1f8a8075961400b1b4606eb12fd81b"};
    
                Console.WriteLine(ZipExtentionMethodTest(parms, values));
                Console.ReadLine();
            }
    
            public static string ZipExtentionMethodTest(string[] paramerters, string[] values)
            {
                // parse dict
                string ptrs = null;
    
                var parmStr = paramerters.Zip( values, (paramerter, value) => new
                {    
                    inplace = ( values[values.Length - 1] !=  value ?
                        paramerter + "=" + value + "&" : paramerter + "=" + value
                    )
                });
    
                foreach (var item in parmStr)
                {
                    ptrs += item.inplace;
                }
    
                return ptrs;
            }
        }
    }
    
    
    위 코드랑 비교해 본다면 전 코드의 경우 Object 배열 타입의 dict란 변수를 받아서,  select  구문으로 key 와 value 값을 결합하고 인덱스가 마지막일 경우 다른 조건의 결합 을 사용하게 되어 있습니다.

    그런데 Zip 코드를 이용하면, 간단히 두개의 배열로 부터 인자를 받아 하나로 합칠 수 있지요. 하지만 인덱스를 사용할 수 없어서 조건은 배열의 길이를 이용하였습니다. 

    Zip을 사용하면 두개의 배열에 있는 element 들을 하나로 합칠 때 사용하면 좋은 방법이 될 것 같네요.


    [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

    [C# 4.0] Duck Typing

    C# 2009. 4. 6. 23:46 Posted by 알 수 없는 사용자
    Dynamic 언어인 루비를 공부해 보신 분은 다음과 같은 구문을 많이 보셨을 겁니다.


    X 라는 변수에 "hello" 라는 문자를 대입하고, 변수 X의 타입은 String입니다.


    그리고 다시 X변수에 100을 넣으면, X변수의 타입은 Fixnum(Ruby에서 Integer를 표현하는 타입입니다)으로 변합니다.

    여기에서도 알수 있듯이 동적인 언어에서는 Type이 동적으로 변합니다. 그래서 이런 속성을 이용해서 duck typing 이란 것을 구현할 수 있는데요. Dynamic language 를 주제로 검색엔진을 통해 검색해보면 항상 빠지지 않고 등장 하더군요.

    그런데 왜 이름이 Duck Typing일 까요?

    Ruby에서 Dynamic Typing에 관한 자료를 찾는 도중에, Duck typing을 좀 더 잘 이해할 수 있는 예제를 C# 4.0으로 구현해 보게 되었습니다.

    참고 소스 : http://rubylearning.com/satishtalim/duck_typing.html


    우선 Duck(오리) 클래스를 만들었고, 오리는 꽥꽥거리기도 하고(quack() 메소드), 수영도 하지요(swim())
    오리만 있나요, 거위(Goose)도 있습니다. 마지막으로 오리의 꽥꽥거리는 소리를 내는 DuckRecoding이란 클래스도 만들었지요.

    이제 꽥꽥거리게 만들어 보자구요.



    2개의 static 메소드를 만들었습니다. parameter로 dynamic type의 duck이란 변수를 주고, 꽥꽥(quark()) 거리거나 수영(swim())하게 만들었습니다. 지금 duck변수는 오리인지, 거위인지, 아님 제 3의 조류인지 알 길이 없습니다. 

    어떤 녀석들인지 확인해 보기로 하죠.


    콘솔 출력을 이용해서. 첫번째 줄은, 진짜 오리로 하여금 꽥~~~~, 두번째 줄은 목소리를 녹음한 녹음기(DuckRecording)로 꽥~~~~~~, 세번째 줄은 오리 수영 시키기, 네번째 줄은 거위 수영시키기입니다.

    이제 결과값을 보겟습니다.



    첫번째 줄의 오리는 꽥~~ 거렷습니다. 두번째 줄은 무응답.... 세번째 줄은 오리가 수영을 하고 있군요. 네번째는 오리가 아닌 거위 수영입니다.  2번째 줄에서 예상되는 값은 꽥~~ 이었는데요, 나오지 않은 이유는 리턴 타입이 잘못 되어 있네요(죄송합니다. T.T).
    아까 이렇게 선언했었지요.
     class DuckRecording
        {
            public void quack() { this.play(); }
            public string play() { return "Quark!"; }
        }


    결론

    위키디피아에서 Duck typing에 관해 다음과 같이 간단하게 적어 놓았네요.
    If it walks like a duck and quacks like a duck, I would call it a duck.
    오리처럼 행동하면 오리라 부를수 있다는 의미. String 처럼 행동한다면, String으로 다루어도 된다는 이야기. 결국 오브젝트의 부모나, 인터페이스의 영향보다, 그 오브젝트가 가진 메소드나 속성에 의해 그 오브젝트의  역활이 결정된다는 표현이 아닐까 하는게 제 생각입니다.

    참고 사항 :  IronRuby에서 Fixnum 타입의 값이 to_f (Float type으로 변환)이 되지 않았습니다. 이유는 잘 모르겠네요. "methods"로 전체 메소드를 보면 to_f가 없는 것 같습니다. 

    제가 알고 있는 Dynamic 언어인, Object C의 경우 Dynamic Object가 메소드를 호출 할 떄  런타임 하에서 그 오브젝트에 속한 메소드를 찾지 못하는 경우 런타임에서 경고로 넘어갑니다만, C# 4.0 에서는 Runtime Error 와 함께 VSTS 2010 이 죽고, Virtual PC가 얼어버리네요. 이 점은 정식 버젼이 나오면 다시 확인해 보고 싶습니다.

    comment 를 확인하다 보니, 제가 쓴 글에 잘못된 내용이 있는 것 같네요. 그래서 글을 좀 수정했고요, 좋은 의견과 배움에 감사드립니다.  


    [C# 4.0] Named and Optional Parameters

    C# 2009. 4. 6. 15:34 Posted by 알 수 없는 사용자
    
    Flex로 ActionScript 프로그래밍을 하다 보면 아래와 같은 메소드 선언을 많이 볼수 있습니다.
     
    public function hitTestPointer(x:Number, y:Number, shapFlag:Boolean = false): Boolean
     
     Parameter 값에 Default 값을 넣어 사용하는 것은 ActionScript로 작업하고 있는 저로는 익숙한 표현이었지만, 가끔 다른 언어를 사용하다 보면 이런 표현이 있었으면 좋겠다고 생각했는데, 마침 C# 4.0에서 이런 문법을 사용할 수 있게 되었습니다. 위 코드 처럼 Boolean 타입인 shapFlag 의 값에 false 값을 넣어주는 것을 Optional Parameter 라고 하고, Default Parameter라고 부르기도 하더군요.
    (지금 코드는 C#입니다)

     
    public class Test
    {
       public bool  hitTestPointer(float x, float y, bool shapeFlag = false)
       {
          .....................
       }
    }
     
     
     그런데, Actionscript 와 차이점이 있다면, Parameter의 위치를 사용자가 원하는 대로 바꿀 수 있다는 점입니다. 예를 들어 Actionscript의 경우 Optional parameter 의 선언은 일반 parameter 뒤 이거나, 아니면, 전부 Optional parameter 로 선언해야 합니다. 

    예들 들어
    Actionscript )
    hitTestPointer( 10, 10)  ------------>  OK
    hitTestPointer( 10, false, 10) ---------> Error
    hitTestPointer( 10, false) ------------> Error
    하지만, C# 4.0 에서는 Named parameter 로 이 문제를 해결할 수 있습니다.
    C# 4.0 )
    hitTestPointer( 10, 10)  ------------>  OK
    hitTestPointer( x: 10, shapFlag: false, y: 10) ---------> OK
    hitTestPointer( x: 10, shapFlag: false) ------------> Error (y는 Optional Parameter 가 아님)
    두번째 포스팅 하는 건데, (첫번째 포스팅은 내용에 맞지 않아 삭제함) 공부하다 제가 느낀 점만 간단히 적다보니 제대로 내용이 전달 되는 건 지 모르겟습니다. 관심 분야는 RIA 인데, C# 4.0 공부를 않 할 수가 없더라고요. 제 공부방향은 C# 4.0 의 내용을 파악한 뒤에 RIA 쪽으로 넘어가는 겁니다. 그런데, 아직 3.5 도 제대로 잘 모른다는...   어여튼 열심히 ^^

    Welcome to F#(1) - 첫만남.

    F# 2009. 4. 5. 20:58 Posted by 알 수 없는 사용자

    What is F#?
    F#에 대해서 들어본 적이 있으신가요? 아니면, Functional programming language 혹은 함수형 언어라고는 들어본적이 있으신가요? 아마도 최근에 부각되었었던 Erlang이나 기존의 Lisp, Scheme등을 들어보셨거나, 공부해보신 분이라면 알고계시리라 생각합니다. F#은 닷넷에서 돌아가는 함수형언어이고 현재 CTP(Community Technical Preview)버전이 공개된 상태입니다. 차후에 VSTS 2010에 포함되어서 나올 예정이구요. 


    함수형 언어는 왜 배워야 하는데?
    C#이나 Java와 같이 입력을 받아서 어떻게 그걸 처리할지 주저리주저리 이야기 해줘야 하는 언어는 명령형 언어(Imperative programming language)라고 합니다. 하지만, 그와 반대로 어떻게 할건지 보다는 무엇을 처리할지에 더 관심을 두는 형태를 선언형 언어(Declarative programming language)라고 합니다. 정규식이나 함수형언어 같은 언어가 포함되지요. 예를 들어보면 정규식같은 경우는 어떤 패턴을 잡을지에 관심이 집중되어 있습니다. 하지만, 어떻게에 대해서는 관심이 없지요. 즉, 명령형 언어와 선언형 언어는 서로 관점이 틀리기 때문에 서로 유용하게 쓸 수 있는 분야도 틀릴 수 있다는 것입니다.

    물론, Anders Hejlsberg가 JAOO의 강연에서 이야기 한것처럼 함수형언어와 기존의 명령형언어(Imperative programming language)는 서로 다른 장점이 있기 때문에, 어떤 상황에서 어떤 언어를 선택하는 것이 옳은지 명확하게 이야기 할 수 는 없습니다. 하지만, 함수형언어는 나중에 더 자세히 다룰 수 있겠지만 Immutable, 즉 한번 값을 입력하면 다시는 값이 변경될 수 없는(C#에서 readonly를 생각하면 되겠죠.)걸 이야기 하는데, 이때문에 병렬적으로 실행되는 환경에서 흔히 문제가 되는 여러 스레드가 하나의 값에 접근할때 값이 잘못변경될 위험이 없습니다. 그래서 병렬 프로그래밍에서 가장 유용한 프로그래밍 모델로 생각되고 있으며 실제로 얼마전에 Erlang이 이슈가 되었던 것도 그런이유 때문이었던 것 같습니다.

    근데 왜 F#을 공부해야 하는데?
    개인적으로는 점차 플랫폼의 영향력이 커진다는 느낌을 받습니다. 그리고 기존의 플랫폼에 워낙 많은 기능이 이미 구현되어 있고, 그런 언어의 실행환경에 대해서는 신경을 쓰지 않고, 자신의 언어가 가질 특징들에 집중해서 새로운 언어를 만드는 것도 점차 중요해지는 것 같구요. 꽤나 히트했던 Ruby가 JRuby와 IronRuby로 자바와 닷넷에 각각 편입되는 것을 보더라도 그런 것 같습니다. 단순히 플랫폼의 덕만 보는게 아니라, 그 플랫폼에서 사용되는 다른 언어들과도 교차적으로 사용될 수 있다는 점도 꽤나 큰 이익이 아닌가 생각합니다. 이 주제에 대해서 잘 설명을 해주신 장성진님의 글을 읽어보시면 더 좋을 것 같습니다.

    F#을 배워야 하는 이유는 하나의 어플리케이션을 개발할때, C#을 메인언어로 놓고 개발하면서 F#으로 개발했을때 이익이 되는 부분이라면, F#으로 개발해서 조합을 할 수 있겠죠. 저 역시도 그런 가능성을 가장 기대하고 있습니다.

    앞으로의 방향은 어떻게 되니?
    개인적으로 기존에 Scheme을 공부해본적이 있긴하지만, 워낙 잠깐이라 딱히 많이 아는건 없습니다. 그래서 공부해가면서 고민해가면서 여기에 적어볼 생각입니다. 그래서 내용이 엄밀하지 못하거나 심도가 없을 수도 있는데, 그런부분은 피드백으로 잘 훈계해주시면 완전 감사하겠습니다.

    F#을 설치해보자
    시작이 반이라고 했으니, F#을 설치하면서 빨리 반을 끝내보도록 하죠. F#은 현재 CTP버전이 나와있고, 비주얼 스튜디오 2008에서도 사용할 수 있습니다. 그리고 비주얼 스튜디오가 없더라도 명령행툴이 있기 때문에, 거기서 작업을 하면서 공부하실 수 있습니다. 물론 비주얼 스튜디오가 있음 더 편하겠죠. 일단 여기에서 F# CTP버전을 받을 수 있습니다. msi파일을 받아서 실행하시면 되구요, zip파일은 윈도우가 아닌 운영체제에서 압축을 풀어서 readme를 보라고 하는데, 별로 보고싶지 않아서 확인은 안 해봤습니다.(역시 글로쓰면 농담이 안살아나는 군요-_-)

    F#과 만나서 Hello를 외쳐보자
    Hello를 외치려면 일단 만나야 겠죠. 그럼, F# Interative를 실행해보죠. 그러면 아래와 같은 창이 하나 뜹니다.


    궁금한게 있으면 #help;;를 쳐보라는 친절한 말까지 남겨주시죠. 여기서 우리는 F# Interative에게 뭔가 부탁하려면 '# + 부탁할내용 + ;;'을 해야 한다는 사실을 알 수 있죠. 참고로 F# Interactive에서 나가게 해달라고 부탁하는 말은 "#quit;;"입니다. 그러면, 언제나 처음 언어를 접하면 서로 인사를 나누어야 하니 Hello World를 한번 외쳐보도록 하죠.



    위와 같이 한번 쳐보시죠. let HelloWorld~~;;는 선언부이고, 그 아래는 함수호출 결과입니다. 언어가 다르다 보니 모양도 좀 틀립니다. 우선 F# Interative에서는 하나의 의미를 갖는 문장이 끝난다는걸 ';;'을 통해 알립니다. 그래서 위문장은 ';;'를 만날때 까지 하나의 단위로 인식해서 함수를 선언해주는 것이고, 아래 문장은 호출이라는 것을 파악하는 것이죠. 그러면 이제 나가게 해달라고 부탁하시고 비주얼 스튜디오에서도 Hello World를 외쳐보도록 하겠습니다.


    새프로젝트를 눌러보시면 윗 그림과 같이 Visual F#이 추가된걸 보실 수 있습니다. 그럼 프로젝트를 생성해서 아래그림 처럼 코드를 쳐보시죠.



    그리고 정말 친숙한 명령 Ctrl+F5를 누르면, 정말 친숙한 콘솔창에 아래 그림과 같이 결과가 나옵니다.(너무 친숙해서 마치 집에 있는거 같군요. 이래서 집나가면 개고생이라나 봅니다.)



    그리고 비주얼스튜디오에서 F# Interative창을 띄워서 평가하고 싶을때는 아래 그림과 같이 "보기 -> 다른 창 -> F# Interactive"를 눌러줍니다.



    그러면, 아래 그림과 같이 하단부에 F# Interactive가 뜨게됩니다.



    그리고 이제 비주얼 스튜디오에서 작업한 내용을 F# Interactive에서 확인해볼 수 있습니다. F#같은 함수형 언어에서는 모든 코드가 컴파일되는 것이 아니고 한줄 한줄 평가(Evaluation, 혹은 그냥 Eval)하게 되는데요, 작업 부분중에 평가 해보고 싶은 부분만 드래그해서 F# Interative에서 결과를 확인해볼 수 있습니다. 평가하는 방법은 우선 평가하고 싶은 부분을 정확하게 드래그 해서 마우스 오른쪽 버튼을 누르고 "Send to F# Interative"를 누르거나 "Alt + Enter"를 누르시면 됩니다. 아래 그림은 함수선언부를 먼저 F# Interactive로 보내서 평가하고 그 다음에 함수호출부분을 다시 평가해서 얻은 결과물입니다.



    이제는 우리가 헤어져야 할시간, 다음에 다시 만나요
    자 이제, F#과의 첫 인사를 마쳤습니다. 어떠셨나요? 제가 실력이 부족하고 글솜씨가 딸려서 좀 설명이 부족한 부분이나, 틀린 부분이 있을 수도 있습니다. 그럴땐 따뜻한 피드백으로 화답해주셨으면 좋겠습니다.(차가운 피드백은 반사하겠습니다-_-) 저 역시 아직 함수형언어 자체에 대한 이해도 부족하고, F#도 잘 아는 상태가 아니라서 인지 앞으로 어떻게 계속 글을 이어나가야 겠다는 명확한 생각은 없는 상태고 그저 글을 계속 쓰면서 정해나갈 생각입니다. 다음번 포스트에서는 간단한 예제를 통해 F#에 대해서 좀 더 자세한 설명을 드리고 명령형언어와 함수형언어의 차이에 대해서 좀 더 알기 쉽게 설명해볼까 하는 생각을 갖고 있습니다.(말이 길어지면, 둘중 하나만 하고요-_-) 이 글이 도움이 되는 분들이 있길 바라고, 다음 포스트로 뵙겠습니다.

    참고자료
    1. Expert F#, Don Syme, Adam Granicz, Antonio Cisternino, APRESS.
    2. http://blog.java2game.com/229
    3. http://jaoo.blip.tv/file/1317881/
    4. http://en.wikipedia.org/wiki/Functional_programming
    5. http://en.wikipedia.org/wiki/Imperative_programming
    6. http://en.wikipedia.org/wiki/Declarative_programming

    VSTS 2010 팀 맴버 지원을 마감합니다. 현재 아키텍트, 게임, RIA, 웹 분야 등 많은 분들께서 VSTS 2010 팀에 지원해 주셨고, 이토록 VSTS 2010 에 많은 관심을 갖고 계신 분들이 많을 줄은 몰랐네요.

     

    지원해 주신 분들 모두 감사드립니다.

     

    조만간 팀 맴버의 전체 모임이 있을 예정이니, 그 이후에 맴버 소개와 함께 이야기 거리를 전해드리도록 하겠습니다.

    [MEF] 3. Export 선언

    Managed Extensibility Framework 2009. 3. 29. 21:03 Posted by POWERUMC
    Exports 선언
     
    MEF 는 Export 를 통해 외부로 구성요소를 노출할 수 있습니다. Export 는 System.ComponentModel.Composition.ExportAttribute 특성을 통해 선언합니다. 이 특성은 클래스 뿐만 아니라 프로퍼티와 메서드에도 선언을 할 수 있습니다.
     
     
    구성요소 Export 하기
     
    ExportAttribute 특성을 사용하여 아래와 같이 구성요소를 외부로 노출하게 됩니다. ExportAttribute 은 몇 가지의 시그너처(Signature) 를 제공하는데 매개변수를 생략하게 될 경우 MEF 은 클래스의 타입으로 Contract 를 매핑하게 됩니다.
     
    [Export]
    class MessageSender
    {
     
    }
     
     
    프로퍼티 Export
     
    프로퍼티를 Export 하는 방법입니다. 프로퍼티를 Export 할 수 있게 되어 여러 가지 면에서 유리할 수 있습니다.
     
    Core CLR 이 제공하는 타입(Type) 뿐만 아니라 외부의 다양한 타입(Type) 을 사용할 수 있습니다. 프로퍼티에 Export 를 선언할 수 있음으로써 Export 를 구조적으로 분리하여 단순화 할 수 있습니다. 그러므로 같은 구성요소 내에서 Export 간의 Related 관계를 가질 수 있습니다.
     
    아래의 코드와 같이 Timeout 프로퍼티는 Contract 를 맺게 됩니다.
     
    public class Configuration
    {
       [Export("Timeout")]
       public int Timeout
       {
           get { return int.Parse(ConfigurationManager.AppSettings["Timeout"]); }
       }
    }
     
    [Export]
    public class UsesTimeout
    {
       [Import("Timeout")]
       public int Timeout { get; set; }
    }
     
     
    메서드 Export
     
    구성요소의 메서드를 Export 할 수 있습니다. 메서드의 Export 는 기본적으로 대리자(Delegate) 를 통해 호출하게 됩니다. 메서드를 Export 하게되면 보다 더 세세한 제어를 가능하게 하고, 심플하게 방법으로 Code Generating 이 가능합니다.
     
    public class MessageSender
    {
       [Export(typeof(Action<string>))]
       public void Say(string message)
       {
           Console.WriteLine(message);
       }
    }
     
    [Export]
    public class MessageProcess
    {
       [Import(typeof(Action<string>))]
       public Action<string> MessageSender { get; set; }
     
       public void Send()
       {
           MessageSender("Call send process in MessageProcess");
       }
    }
     
    그리고 ExportAttribute 은 타입(Type) 대신 문자열을 사용하여 Contract 를 사용할 수 있습니다.
     
    public class MessageSender
    {
       [Export("MessageSender")]
       public void Say(string message)
       {
           Console.WriteLine(message);
       }
    }
     
    [Export]
    public class MessageProcess
    {
       [Import("MessageSender")]
       public Action<string> MessageSender { get; set; }
     
       public void Send()
       {
           MessageSender("Call send process in MessageProcess");
       }
    }
     
     
    아래의 소스 코드는 이번 예제에서 사용된 전체 소스 코드입니다.
    namespace ExportSample
    {
       class Program
       {
           [Import]
           MessageProcess MessageProcess { get; set; }
     
           [STAThread]
           static void Main(string[] args)
           {
                 Program p = new Program();
                 p.Run();
     
                 p.MessageProcess.Send();
           }
     
           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 class MessageSender
       {
           [Export("MessageSender")]
           public void Say(string message)
           {
               Console.WriteLine(message);
           }
       }
     
       [Export]
       public class MessageProcess
       {
           [Import("MessageSender")]
           public Action<string> MessageSender { get; set; }
     
           public void Send()
           {
                 MessageSender("Call send process in MessageProcess");
           }
       }
    }
     
     
    Export 요약
     
    이렇게 ExportAttribute 을 사용하여 Contract 를 제공하는 것은 굉장히 중요한 의미를 가지게 됩니다. 플러그인 모델(Plugin Model) 에서 Export 는 구성요소를 외부로 노출하는, 즉 Contract 의 방법을 제공해 주게 됩니다.
     
    http://blog.powerumc.kr/upload/Image/NET/NET-Framework/MEF1/capture1.jpg
     
    Contract 맺음으로써 개발자는 Contract Base 로 단지 Contract 만 제공받으면 됩니다. 이러한 Contract 는 제한된 상호작용을 극복하여 대부분의 커플링(Coupling)을 해소할 수 있으며, 플로그인 모델(Plugin Model) 에서 보다 쉽게 구성요소를 캡슐화 할 수 있습니다.

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

    [MEF] 6. Lazy Exports  (0) 2009.04.13
    [MEF] 5. Catalog 사용  (0) 2009.04.09
    [MEF] 4. Import 선언  (0) 2009.04.07
    [MEF] 2. Parts 와 Contracts 선언  (0) 2009.03.22
    [MEF] 1. Managed Extensibility Framework 이란?  (2) 2009.03.16
    안녕하세요. 여러분~
    저희 팀 블로그는 차세대 개발 플랫폼인 .NET Framework 4.0 과 VSTS 2010 정보를 제공하는 공식 팀 블로그 입니다.
     

    VSTS 2010 팀 블로그 소개 참조
     

     
    저희 팀 블로그에서는 앞으로 다가오는 .NET Framework 4.0 과 VSTS 2010 를 체험하여 정보를 제공하며 함께 지식을 공유할 수 있는 팀원을 모집하고자 합니다.
     


     
    l 저희 팀에서 함께 팀 블로그와 스터디를 운영하실 새로운 팀원을 모집합니다.
     

    개요
    차세대 개발 플랫폼인 .NET Framework 4.0 과 VSTS 2010 정보를 제공하며, 스터디 활동을 통해 정보의 교류 및 친목을 도모하고자 합니다.
    팀 블로그
    팀 블로그를 통해 자신만의 분야 또는 배우고 싶은 분야를 공부하여 블로그에 게시할 수 있는 공간을 제공합니다. 다양한 분야의 전문가들도 함께 참여하여 VSTS 2010 에 대한  중요한 피드를 제공합니다.
    스터디
    매월 1회 스터디를 운영합니다. 서로 기술적인 부분을 공유하며 토론할 수 있는 시간을 갖습니다. (예정)

     
     
    l 아래와 같이 열정을 지닌 분들이라면 언제든지 메일 주시기 바랍니다.
     

    대상
    무관
    지원 자격
    1.     .NET Framework 3.5 와 Visual Studio 2008 의 신 기능에 대해 알고 있는 분
    2.     자신의 블로그를 운영하고 계신 분
    3.     무언가에 도전하고 싶은 열정을 갖은 분
    모집 분야
    l Cloud Development
    l Parallel Development
    l Web Development
    l Windows 7 Development
    l RIA Development
    l Architect Development
    l Office Business Application Development
    l .NET Framework 4.0
    l Visual Studio 2010
    l Visual Studio Team System 2010
    l ETC…

     
     
    l 메일로 지원해 주세요
     
    umc골벵이dotnetxpert.com로 아래와 같은 형태로 지원 메일을 보내주시면 됩니다.
     

    이름
    홍길동
    블로그
    http://자신의 블로그 주소
    소개
    회사 및 소속, 자신의 소개
    지원 분야
    Web Development (중복 가능)

     
     
    먼저 도전하는 당신이 바로 주인공입니다. ^^
    시작하기 전에
     
    MEF 는 이미 CodePlex 사이트의 Wiki 에 코드를 중심으로 설명이 잘되어 있습니다. 그렇기 때문에 저도 CodePlex 의 사이트를 참고하여 나름대로 각색하여 작성을 하고자 합니다. 레퍼런스가 이미 CodePlex 에 충분하지만, 저는 나만의 시각에서 바라보고 느낀 바를, 그리고 소스 코드를 만들어 가고자 합니다^^ (사실 Wiki 의 설명은 미약할 다름입니다^^;)
     
    CodePlex 의 Wiki 를 먼저 보실 분은 최신 버전이 적용이 되지 않은 예제도 있으니 이런 부분은 조심해서 리뷰하시기 바랍니다.
     
     
    어플리케이션에 MEF 호스팅하기
     

    [그림1] Composition Container
     
    Composable Part
     
    MEF 에 어플리케이션을 호스팅하기 위해서는 몇 가지의 반복적인 절차를 거치면 됩니다. 먼저 MEF 를 호스팅할 수 있는 컨테이너(Container) 를 만들어야 합니다. 컨테이너는 MEF 에서 상위 그룹에 존재하며 MEF 의 파트(Part) 를 관리하며 핵심 역할을 담당합니다.
     
    MEF 의 컨테이너는 배치(Batch) 를 구조적으로 구성하고 캡슐화 합니다. 배치(Batch) 의 각 구성 단위를 파트(Part) 라고 부릅니다. 각 파트(Part) 는 닷넷 어셈블리에서 타입(Type) 이 될 수 있으며, 타입(Type) 을 배치(Batch) 로 등록할 수 있습니다.
     
    파트(Part) 는 메인 호스트(Main Host) 가 반드시 포함되어야 하며, 아래의 소스 코드에서 보는 것처럼 this 키워드가 바로 메인 호스트(Main Host) 가 됩니다.
     
    Contract
     
    이러한 Composable Part 는 다른 컴포넌트와 의존 관계를 갖지 않습니다. 모든 외부 기능(Export) 는 계약(Contract) 를 맺게되며 이것이 필요할 경우에는 Import 할 수 있습니다.
     
    MEF 의 컨테이너는 Contract 정보의 타입 정보나 메타 데이터를 통해 Export 와 Import 를 매칭합니다.
     
     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
     
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            p.Run();
        }
     
        public void Run()
        {
            var container = new CompositionContainer();
            var batch = new CompositionBatch();
            batch.AddPart(this);
            container.Compose(batch);
        }
    }

     
    이러한 파트(Part) 를 제어하는 작업은 어플리케이션 차원에서 유일해야 하므로 스레드(Thread) 작업에 안전하도록 lock 으로 블로킹(Blocking) 되어있습니다.
     
    이 작업은 메인 호스트(Main Host) 를 등록하는 과정에 불과하며 실행 시에 아무런 결과가 없습니다.
     
     
    외부로 기능 노출하기 (Export)
     
    이제 어떤 플러그인(Plugin) 을 외부로 노출해야 합니다. 외부로 노출하는 이유는 내/외부에서 노출된 확장 기능을 가져다 쓰기 위해서입니다. 확장 기능을 노출하기 위해서는 단지 Export Attribute 을 정의해 주면 됩니다.
     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
     
    namespace MEFLab_Hosting_MEF
    {
        class Program
        {
            static void Main(string[] args)
            {
                   Program p = new Program();
                   p.Run();
            }
     
            public void Run()
            {
                   var container = new CompositionContainer();
                   var batch = new CompositionBatch();
                   batch.AddPart(this);
                   container.Compose(batch);
            }
        }
     
        public interface IHelloWorld
        {
            void Say();
        }
     
        [Export(typeof(IHelloWorld))]
        public class HellowWorld : IHelloWorld
        {
            public void Say()
            {
                   Console.WriteLine("Hello MEF!");
            }
        }

     
    인터페이스(Interface) 를 구현한 HelloWorld 클래스는 Export Attribute 를 정의합니다. Export 의 파라메터는 메타 데이터(Meta Data)로 사용되기 때문에 타입(Type) 을 정의해 주어야 합니다.
     
    혹자는 왜 인터페이스를 정의해야 하느냐고 궁금해 하기도 합니다. 정답을 드리자면, 반드시 인터페이스를 정의하지 않아도 됩니다. 하지만 특히 MEF 에서 인터페이스는 다형적이고 표준적인 메타 데이터를 제공하기 위해 인터페이스를 선언하여 사용하는 것이 좋을 것 같네요^^
     
     
    외부 기능 가져오기 (Import)
     
    Export Attribute 으로 외부로 노출된 확장 기능은 Import Attribute 으로 가져올 수 있습니다. 단, 배치(Batch) 의 파트(Part) 로 등록이 되어 있어야 합니다. 내부적으로 Import 의 타입을 생략할 경우 Export 의 타입의 메타 데이터를 통해 Import 의 개체를 쿼리(Query) 하여 생성하게 됩니다.
     

    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            p.Run();
        }
     
        [Import]
        IHelloWorld HelloWorldCompoent { get; set; }
     
        public void Run()
        {
            var container = new CompositionContainer();
            var batch = new CompositionBatch();
            batch.AddPart(new HellowWorld());
            batch.AddPart(this);
            container.Compose(batch);
     
            HelloWorldCompoent.Say();
        }
    }
     
    public interface IHelloWorld
    {
        void Say();
    }
     
    [Export(typeof(IHelloWorld))]
    public class HellowWorld : IHelloWorld
    {
        public void Say()
        {
            Console.WriteLine("Hello MEF!");
        }
    }

     
    이 예제에서 알 수 있듯이 코드에서 모듈(Module) 이나 타입(Type) 의 관계를 크게 신경 쓰지 않았습니다. Export 와 Import 를 통해서 의존(Dependency) 는 어느 정도 해소된 것처럼 보입니다. (인터페이스만 잘 활용하면 MEF 없이도 충분히 가능합니다)
     
    이것이 끝이라면 정말 재미가 없겠죠. 차차 나오게 될 내용이지만, 이러한 Export 와 Import 를 활용하고 Lazy Load, 그리고 메타 데이터를 이용한 쿼리(Query) 를 활용하게 되면 복잡한 기능을 획기적으로 단순화 할 수 있습니다.
     
     

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

    [MEF] 6. Lazy Exports  (0) 2009.04.13
    [MEF] 5. Catalog 사용  (0) 2009.04.09
    [MEF] 4. Import 선언  (0) 2009.04.07
    [MEF] 3. Export 선언  (0) 2009.03.29
    [MEF] 1. Managed Extensibility Framework 이란?  (2) 2009.03.16
    MEF (Managed Extensibility Framework) 란?
     
    Menaged Extension Framewkr(이하 MEF) 란? 가장 쉽게 얘기하자면, 어플리케이션과 컴포넌트의 재사용성을 높일 수 있는 프레임워크입니다. 기존의 어플리케이션은 하나의 목적을 하나의 어플리케이션으로 구현한 정적인(Statically) 어플리케이션이라면, MEF 는 보다 동적인(Dynamically) 어플리케이션을 구축할 수 있는 새로운 라이브러리를 제공합니다.
     
    기존의 정적인 어플리케이션은 새로운 요구사항으로 기능을 확장할 필요가 있을 경우 새로운 빌드 버전을 필요로 합니다. 그리고 새로운 빌드 버전은 기존 어플리케이션과 확장된 기능간에 종속적인 관계를 탈피할 수 없었습니다. 이미 프로그램 언어를 사용하여 코드를 작성하는 분들이라면 반복적이거나 확장에 대해 많은 고민을 한번쯤 해보았을 것입니다.
     

    [그림1] MEF 의 컨셉 이미지
     
    MEF 는 플랫폼의 저레벨(Low Level) 에서 공통된 추상적인 기능을 제공하고 여러 곳에 흩어진 이중 작업을 감소시킬 수 있습니다.
     
    몇 달 전 마이크로소프트에서는 Application Framework Core 팀이라 부르는 팀이 만들어졌다고 합니다. 이 팀은 ASP.NET, Windows Forms, WPF, Silverlight 의 여러 플랫폼에서 동작하기 위한 BCL(Base Class Library) 과 같은 역할을 한다고 합니다.
     
     
    MEF 는 플러그인 모델(Plugin Model)
     
    MEF 는 플러그인 모델(Plugin Model) 이라고도 부릅니다. 플러그인 모델을 잘 모르신다면, 전기 콘센트의 플러그를 연상하시면 됩니다. 전기 콘센트의 플러그는 그 수가 제한되어 있지만 어댑터를 추가로 구매하여 꽃으면 몇 개의 콘센트를 꽃을 수 있습니다. 그리고 TV 나 컴퓨터를 사용하고 싶다면 콘센트에 꽃기만 하면 TV 와 컴퓨터를 동작시킬 수 있습니다.
     

    [그림2] MEF 는 플러그인 모델(Plugin Model) 이다. (출처는 여기)
     
    만약 더 좋은 TV 나 컴퓨터가 생겼다면 플러그를 빼고 더 좋은 TV 나 컴퓨터의 플러그를 콘센트에 꽂기만 하면 됩니다.
     
    이처럼 MEF 는 어플리케이션의 확장을 위한 보다 유연한 아키텍처를 제공하며, 약간의 개념만 이해한다면 사용하기도 쉽습니다.
     
     
    어디서 많이 본 듯한 아키텍처?
     
    맞습니다. 저도 MEF 를 처음 보는 순간 느꼈습니다. MEF 의 외관은 마치 DI(Dependency Injection) 과 IoC(Inversion of Control) 의 그것과 매우 유사해 보였습니다.
     
    용어 설명
     
    DI(Dependency Injection) / 의존성 주입
    객체간의 의존성과 결합도를 낮추기 위한 기술
     
    IoC(Inversion of Control) / 역제어
    인스턴스의 관리를 컨테이너에서 인스턴스의 생성과 소멸의 생명주기를 관리
     
    하지만 MEF 는 DI 나 IoC 와 전혀 다릅니다. 위에서 얘기한대로 MEF 는 플러그인 모델입니다. 어플리케이션의 확장을 위한 프레임워크이며, DI 와 IoC 는 잊어버리십시오! 아래의 단원에서 DI 와 IoC 를 잊을 수 있는 분명한 근거를 설명하도록 하겠습니다.
     
     
    플러그인 모델(Plugin Model) 로 뭘 할 수 있나요?
     
    MEF 의 플러그인 모델(Plugin Model) 은 보다 나은 확장성을 제공해 줍니다. 마치 Visual Studio 의 Addin 을 연상하시면 됩니다. Visual Studio Addin 은 Visual Studio 의 기능을 쉽고 강력하게 활용할 수 있도록 도와주며 전혀 새로운 기능을 추가할 수 있는 플러그인(Plugin) 입니다. 그럼 MEF 의 플러그인 모델(Plugin Model) 은 어떠한 장점이 있을까요?
     
    MEF 의 플러그인 모델은 아래와 같은 장점을 제공합니다.
     
    l 확장 기능에 대한 인스턴스를 생성하는 방법(SingleCall, Singleton)을 제공하며, 인스턴스의 회수할 수 있어야 합니다.
    l 상호작용을 할 수 있습니다. 확장 기능간에 메시지의 전달이 쉽고 용이해야 합니다. Global Service 처럼 상호간의 인터페이스가 제공되어야 하고 이러한 메시지에 응답할 수 있어야 합니다.
    l 확장 기능은 Lazy Load 할 수 있어야 합니다. 확장 기능은 원하는 시기에 로드해야 합니다. 마치 VSIP(Visual Studio Integration Package) 의 VSCT 와 같이 인터페이스나 이벤트는 노출이 되어 있지만 실제로 확장 기능이 로드된 것은 아닙니다.
    l 확장이 용이해야 합니다. 예를 들어, 확장 기능이 특정 폴더(Addin 폴더라고 가정)로 복사된다면 이를 감지하여 인터페이스를 제공하거나 확장 기능이 활성화 되어야 합니다.
    l 교체가 쉬워야 합니다. 새로운 기능이 추가된 확장 기능은 교체가 쉬워야 하며, 필요 없어진 확장 기능을 언로드(Unload) 할 수 있어야 합니다.
     
    MEF 는 여러분의 정적인 어플리케이션에 동적인 생명력을 불어넣어 줄 수 있으며, 그 근간은 바로 플러그인 모델(Plugin Model) 입니다.
     
    이러한 플러그인 모델은 근본적인 상호간의 의존(Dependency) 관계를 보다 자연스럽게 해결할 수 있으며, 유연하고 매끄럽게 다룰 수 있을 것으로 기대합니다.
     
    MEF 설치하기
     
    MEF 는 .NET Framework 4.0 에 포함될 예정입니다. 하지만 아쉽게도 .NET Framework 4.0 CTP 버전에는 포함되어 있지 않기 때문에 Visual Studio Team System 2010 의 VPC 이미지에서도 테스트할 수 있는 환경이 갖추어지지 않았습니다.
     
    현재 2009-03-16 기준으로 MEF 는 Preview 4 버전이며 CodePlex 에서 소스코드와 바이너리를 다운로드 받을 수 있습니다.
     
    MEF (Managed Extensibility Framework) 다운로드
     
     
     
    시작이 반이다! 친절한 HelloWorld 따라하기
     
    자… 이제 MEF 도 설치했고 언제나 그렇듯 HelloWorld 를 콘솔에 출력하는 코드를 작성해 보도록 합시다. 소스 코드에 대한 설명은 다음 단원으로 넘기도록 하고, 오늘은 MEF 가 어떻게 동작하는지 눈대중만 익히시면 될 것 같습니다.
     
    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 ConsoleApplication1
    {
           class Program
           {
                 static void Main(string[] args)
                 {
                        Component com = new Component();
                
                        var catalog = new AggregateCatalog();
                        catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
     
                        var container = new CompositionContainer(catalog);
                        var batch = new CompositionBatch();
                        batch.AddPart(com);
                        container.Compose(batch);
     
                        com.HelloWorldComponent.Say();
                 }
           }
     
           public class Component
           {
                 [Import]
                 public IHelloWorld HelloWorldComponent { get; set; }
           }
     
           public interface IHelloWorld
           {
                 void Say();
           }
     
           [Export(typeof(IHelloWorld))]
           public class HelloWorld : IHelloWorld
           {
                 public void Say()
                 {
                        Console.WriteLine("Hello MEF");
                 }
           }
    }
     
     
    출력 결과는
     

    [그림3] 소스 코드 실행 결과
     
    혹자는 HelloWorld 를 찍는데 왜 이렇게 많은 코드가 필요한가에 불만이 있을지도 모릅니다. 맞습니다. 단순히 결과가 HelloWorld 가 출력되기만 바란다면 이렇게 긴(?) 코드는 필요가 없을지도 모릅니다. 하지만 위의 소스 코드는 보다 큰 어플리케이션을 만들기 위한 초석이며 실제로 큰 어플리케이션에서는 훨씬 적은 코드로 복잡한 요구사항을 구현할 수 있을지도 모르는 일입니다^^
     
     
    MEF 는 아직은 Preview
     
    언제나 그렇듯이 새로운 프레임워크는 새로운 패러다임을 가져옵니다. 그리고 보다 나은 아키텍처와 개발 방법을 제시합니다. 물론 MEF 도 더 깊이 살펴볼수록 그 놀라운 기능에 감탄을 하게 될 것입니다.
     
    하지만 아직 MEF 는 Preview 입니다. MEF 의 플러그인 모델은 충분히 활용 가치가 있지만 아직은 실무에서 즉시 도입하기엔 많은 고민이 따를 것 같습니다. 그리고 이런 애로 사항이 아마로 정식 버전에서는 해결되리라 생각합니다. 시간이 되면 이 부분도 한번 다루어 보도록 하겠습니다.

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

    [MEF] 6. Lazy Exports  (0) 2009.04.13
    [MEF] 5. Catalog 사용  (0) 2009.04.09
    [MEF] 4. Import 선언  (0) 2009.04.07
    [MEF] 3. Export 선언  (0) 2009.03.29
    [MEF] 2. Parts 와 Contracts 선언  (0) 2009.03.22
    Kirill Osenkov 은 새로운 Visual Studio 2010 의 Visual Studio 2010 의 언어와 IDE 를 다루는 약 30분 정도 동영상을 촬영하여 공개하였습니다. 이 동영상은 매우 기초적인 내용만을 다루며, 기능에 대한 상세한 부분은 다루지 않는다고 합니다.
     
    동영상에서 보는 Visual Studio 2010 은 WPF Shell 을 적용한 IDE 로 진행합니다. 그리고 이미 Visual Studio 2010 CTP 를 사용해본 분이라면 눈치 채셨겠지만, 동영상의 Visual Studio 2010 은 최근의 Internal Build 버전이라고 합니다. 그렇기 때문에, Visual Studio 2010 CTP 의 불안정한 WPF Shell 의 모습과 비교할 때 더욱 안정적이고 신선한 모습입니다.

    이제 Visual Studio 2010 의 베타 버전이 임박한 듯 합니다.
     
    Visual Studio 2010 Screencast: C# 4.0 Language + IDE + WPF Shell + Editor