Visual Studio 2010 공식 팀 블로그 @vsts2010

Posted by 김병진 Sir.MD
 

이번에는 두번째로 프로젝트를 만들거나 새롭게 cs 또는 vb 파일을 추가할 도움이 되는 것입니다.

 

바로 프로젝트를 생성할 나타나는 화면입니다.

 

 

여기서 우리는 그냥 해당하는 프로젝트를 선택합니다. 그리고 프로젝트 만들기를 하는데 VS 2008에서는 .NET 플랫폼의 선택 기능이 있었습니다. VS 2010에서는 다른 보다 우선 설치된 템플릿과 기존에 만들었던 템플릿들 온라인 템플릿으로 나우어 집니다. 첫번째인 Recent Templates 최근에 만들었던 것으로 여러분들이 기존에 만들었던 템플릿을 불러옵니다.


 

이렇게 기존에 만들었던 템플릿을 가져와서 템플릿을 이용하여 다시 만들수가 있습니다. 다음은 설치된 템플릿입니다.

설치된 템플릿은 여러분들 설치한 VS 2010 언어에 맞추어 템플릿이 표시됩니다.

 

 

 

바로 이렇게 표시가 되죠.^^ 그렇다면.. 바로 위에 있는 Enable loading of per user extensions 틀릭하면 도구상자의 옵션 대화상자를 열고 안에 있는 Extension Manager 메뉴를 호출합니다. 여기서 "Automatically check.." 하면 자동으로 자기가 템플릿 관련 확장을 체크하여 업데이트를 합니다.

 

 

 

다음이 온라인 템플릿입니다. 템플릿은 온라인상에서 템플릿을 불러오는데 바로 사용자를 추가로 새롭게 템플릿을 만든 것을 지원하는 것입니다. 바로 사이트에 있는 내용을 가져오는 것입니다.

 

http://visualstudiogallery.msdn.microsoft.com/en-us

 

 

화면은 이렇게 나오는데 왼쪽 템플릿 메뉴에 여러 목록이 있는데 목록에 해당하는 것을 선택하면 선택한 것만 표시됩니다.

  

 

 물론 기존의 VS 2008 있는 .NET 선택할 있게 되어있는 것은 그대로입니다. 하나 추간된 것은 왼쪽의 Sort by라고 하는 부분이 추가되어 정렬도 있습니다. Sort by VS 2008에서는 없는 것입니다.

 

 

.NET 선택 시에는 2.0 버전부터 선택할 있으며(이건 당근이죠 ^^) 그외 .NET 버전도 선택할 있습니다.

 

 

여기 More Frameworks 부분입니다. 그러면 닷넷 프레임 워크 홈페이지로 이동을 합니다. 주소는

http://msdn.microsoft.com/en-us/netframework 이쪽으로 이동을 하여 추가적인 닷넷 프레임워크를 지원합니다. 사이트에는 지금까지의 닷넷을 다운로드 받을 있도록 하고 있습니다.(예를 들어 SharePoint 2010 개발하기 위하여는 최소한 .NET Framework 3.5 이상을 선택해야 합니다.)

 

이제 이번 글의 하이라트라고 있을까요? Search 입니다.

 

부분은 IE 에서 많이 보셨거나 Windows Desktop Search 사용해 보신 분은 이거~ 하실 겁니다.

바로 VS 프로젝트 템플릿을 찾아주는 역활을 합니다. 제가 여기서 C 라고 입력하면 C 관련된 템플릿이 표시됩니다.


 

cs 하면 C#관련 내용일 것입니다. 이것이 중요한 것은 중간에 파일을 추가할 class 파일을 추가 할때 어떨가요? 해당 프로젝트에서 클래스 하나 추가할 때에도 도움이 됩니다.(사실 중간에 강의 하거나 갑자기 class 파일 하나 만들때 가끔 어디 있는지 못찾을 때가 .)

 

 

바로 생각외로 도움이 것입니다.(사실 정말 도움이 됩니다 ㅋㅋㅋ)

 

오늘은 VS 에서 새롭게 프로젝트를 생성하거나 중간에 프로젝트를 추가 또는 class 이나 cs 또는 aspx파일을 같은 것을 추가하는 대화 상자를 봤습니다. 사실 여기서 집고 넘아가는 것은 개발자에게 파일을 찾기, 또는 추가 할때 위치가 어디 있는지 갑자기 당황 스럽거나 또는 기존에 만들었던 템플릿을 다시 만들고자 할때 쉽고 빠르게 만들 있도록 도와 준다는 것입니다.

 

한가지 확실히 도움을 받습니다. 프로젝트 파일을 추가할 경우 저는 C# , C++, Modeling 같이 있으며 Web Services파일등이 있을 추가하려고 하는 파일을 쉽게 찾아서 추가 한다는 것입니다. 정말 편리합니다. 이것을 조금 유식하게(?) 하면 바로 생산성 향상 측면으로 볼수 있을 겁니다.

 

그럼 다음 번에는 실제 코딩과 관련 있는 부분을 보겠습니다.


크리에이티브 커먼즈 라이선스
Creative Commons License

댓글을 달아 주세요

Posted by 김병진 Sir.MD
 

안녕하세요.^^ 오늘은 IDE 4번째 시간으로 C# 개발자분들은 위한 IDE 소개하곘습니다.

이미 PDC 09 사이트에서 IDE관련한 동영상이 있고 C#, VB.NET 있습니다. 오늘은 C#&VB.NET 으로 개발하시는 분들을 위한 설명을 할까 합니다. 그럼 다음은?? ㅎㅎ VB.NET 입니다. 그리고 다음은 .. Web, C++ Project Management 마지막이 General 마무리를 지으려 합니다. 사실 PDC에서는 별도의 섹션으로 되어 있으나 제가 그냥 하나로 합쳐서 글을 씁니다. 이유는 글을 끝까지 읽어보시면 됩니다.

 

그럼 첫번째 C# 하기 전에 PDC 09 DJ Park 이란 분의 동영상과 자료는 이곳에서 다운로드 받을 있습니다.

 

http://microsoftpdc.com/Sessions/FT35

 

마지막에 분은 1분안에 코딩을 완료하는.. 멋진 모습(?) 보실 있습니다.(저도 해보고 싶지만.. ㅋㅋ 실력이 딸려서 . 그렇지만 언제는 해보고 싶습니다.^^ 세미나에서 1 코딩 완성 ㅎㅎㅎㅎ)

여기서는 동영상에서 나온것을 일단 정리하면서 C# 개발자 분들에게 도움이 될만한 IDE 환경에 대하여 한번 써보겠습니다.

 

 

화면을 아시는지요??(.. 뭐냥. 이건.. 아는 건뎅. .) 화면은 모두 아시겠지만 여러분들이 개발하는 언어를 선택하면 언어에 맞는 환경 구성을 한다는 것입니다. 여기서 환경이라고 하면.. 당근 개발 환경이겠지요. General Development Settings 으로 합니다. 일반적인 개발 환경으로는 개발 속도가 조금 다를것입니다. 일단 C#이므로 C#으로 선택합니다. 물론 중간에 설정 변경을 있습니다. 중간 변경은 Tool 에서 Import and Export Settings 에서 변경할 있습니다.

중간 변경화면 입니다.

 

 

처음 설정을 C# 개발자 하여 환경설정을 해보죠^^(중간에 변경 가능 아시죠?)

 

이렇게 경우 C# 개발 환경으로 변경이 되는데 변경되는 것은 키보드의 단축키와 IDE 환경이 변화게 됩니다.

IDE 환경에서 개발 언어 또는 관리자에 맞게 IDE 환경을 변경하여 최적의 개별 환경을 꾸미는 것입니다. 그럼 C# 최적은 무엇일가? 단축키?( 쓰지 않습니다 .) VS 시작할 시자화면? 모두 개발의 생산성이나 편리성에 맞추어 개발자가 바로 개발을 있다는 것입니다.

 

이렇게 C#으로 선택하면 초기에는 왼쪽은 박스, 오른쪽에는 솔루션탐색기와, 탁색기, 속성만 일단 표시됩니다. 다음 여러분들이 추가/변경 하실 있습니다. 다음은 바로 단축키 입니다. 단축키 부분이 변경이 되는데 소스 코드 한줄 할줄 생성할 여러분들이 단축키를 이용하면 오타를 많이 줄일 있습니다.( 사실 오타 땜시 오타쟁이라고 소문이 .)

 

첫번째는 Modernize the IDE라고 하는 부분입니다.

짧은 영어 실력으로 번역을 해보면 현대적인 IDE 환경을 이야기 합니다. 현대적인? 현대화 라고 하는데.. 정확히는 IDE환경을 조금 현대적으로 또는 우리가 마음대로 바꿀 있도록 했다는 것이며, 요즘 모두 모니터가 2 이상을 사용하는 추세이므로(HDMI까지 하면 노트북에서도 3개까지 가능합니다.) 멀티 모니터의 지원입니다. 사실 멀티 모니터는 개발자들에게 매우 많은 도움이 것이라는 것은 믿어 의심치 않습니다. ^^. 그럼. 현대적인 개발환경에서 첫번재 시작화면을 이야기를 하겠습니다.

 

시작 화면은 이미 변경 가능하다는 것으로, 일단 부분은 다른 블로그에서 소개 했습니다. 시작 페이지의 변경이 없으면 화면에서 왼쪽은 새로운 프로젝트와 시스템 연결선택 메뉴가 있고 바로 밑에 Recent Projects 메뉴가 있습니다. 사실 메뉴는 프로젝트 목록을 불러오는 것인데, 개발자에 따라 사용도 하고 그렇지 않은 경우도 있습니다.(사실 느린 시스템이나 인터넷이 연결 안된 상황에서는 시작페이지를 뛰우지 않습니다 . 가끔 그런상황이 있죠?? ㅎㅎ ) Recent Projects에서 해당 프로젝트의 목록을 이제부터는 Pin 형식으로 고정 사라지게 있다는 것입니다.

 

 

 

  여기서 보시면 제가 빨간색으로 체크한 부분입니다. 부분이 추가됐구요..

 

 

이제 위의 화면은 바로 두번째 메뉴입니다. 바로 해당하는 폴더를 바로 열어 있습니다.(사실 TFS 연결시 실제 폴더를 찾기 위해 소스제어에서 폴더 위치를 가끔 확인하곤 합니다 ^.^ 역시 바부팅 .) 그리고 하나씩 삭제도 가능하죠. ^^ 다음이 바로 밑에 있는 두개의 체크 박스입니다.


 

부분은 시작페이지의 표시 여부와 프로젝트 로드 시에 작업을 체크하는 것입니다. 이것은 그냥 Pass VS 2008에도 있었던 것이므로, 그렇지만. 여기서는 시작페이지에 표시되었다는 것이 조금 다르지요 옛날에는 메뉴에서 환경 설정에서 변경 했는데 편하게 변경되었습니다. 그것이 조금 눈에 들어오고, PDC PPT에서는 첫번째 체크 항목에 대하여 나왔는데 바로 프로젝트를 로드하고 페이지를 닫을 것인지에 대한 체크입니다.

 

다음이 뉴스 부분입니다. 부분은 조금 쉽게 변경되었다고 있습니다. Microsoft 에서 동안 너무 일방적인(?) 부분으로 개발관련 자료는 웹이나 로컬에 MSDN 설치해서 봐야하고 특정 목차가 초급자가 쉽게 접근할 없었습니다. 그런데 ~ 처음에는 Welcome 으로 초급자에게 쉽게 VS 사용법을 접근할 있도록 표시두었다는 것입니다. 전에는? 최신정보도 좋았지만 초급자가 원하는 정보는 찾기가 힘들었다는 것입니다. 그렇다면 고급자는 뉴스 메뉴에 Guidance and Resources 선택하면 조금 고급으로 넘어갑니다.

 

정리하면,  초급자에게 접근하기 좋은 화면 Get Started

              중급자 이상이 보기에 좋은 화면 Guidance and Resources

 

 

 

 

 이렇게 정리할 있습니다.

물론 RSS feed 수저할 있거나 URL 변경, 최신정보로 가져올 있습니다. 변경은 Latest News 에서 수정 또는 갱신이 가능합니다.


 

이제 다음으로 넘어가서 초기 기본으로 제공하는 시작화면에 대하여는 여기서 끝입니다. ^^

그럼 이제 프로젝트 부분인데 이것은 다음에 다시.^^ 글을 씁니다.


크리에이티브 커먼즈 라이선스
Creative Commons License

댓글을 달아 주세요

Posted by 엄준일(땡초)

먼저 이전 포스트의 "MEF 는 Generic Type 을 지원하지 않는다!" 에서 언급했고, .NET CLR 2.0 부터 Generic Type 을 지원함에도 불구하고, .NET Framework 4.0 에 포함되는 MEF 가 Generic Type 을 지원하지 않는다는 것은 솔직히 납득하기가 어렵습니다. MEF 개발 PM 이 말하는 강력한 계약 기반(Strongly Contract Based) 의 모델이라는 점은 머리로는 이해는 되지만, 사실 안될 것도 없습니다. -_-;

MEF 가 갖는 대표적인 키워드인 Composable 은 현재 Generic Type 을 지원하지 않지만, 상당히 매력이 있습니다. 이미 현대적인 프레임워크는 Modular 에 집중하고 있고, MEF 는 더 나아가 Modular + Composite 이라는 상당한 매력을 가진 프레임워크입니다.

일단 서두는 이쯤에서 접어두고, MEF 가 Generic Type 을 지원하기 위한 몇 가지 공개되어 있는 방법을 알아보고, 다시 이야기를 나누어 봅시다. 
   

How to support Generic Type of MEF ?    

첫 번째 방법 - Factory Provider

가장 간단한 방법이 바로 Factory Pattern 을 이용한 방식입니다. 객체의 생성은 Factory 를 통해 생성하도록 하고, Factory 는 객체의 Type 을 받음으로써 객체의 생성을 Factory 에게 모두 의존하는 방법입니다. 우선 아래의 링크를 참고하세요.

 ExportProvider 를 재정의하여 객체의 Type 을 등록하여 원하는 Type 의 객체를 생성하도록 합니다.

1: public interface IService { }

2: public interface IUserService : IService { }

3:  

4: [Export]

5: public class UserController {

6: [ImportingConstructor]

7: public UserController(IUserService userService) { }

8: }

9:  

10: // in your application

11: private void Compose() {

12: var catalog = new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly());

13: var factoryProvider = new FactoryExportProvider<IService>(GetService);

14: var container = new CompositionContainer(catalog, factoryProvider);

15: container.AddPart(this);

16: container.Compose();

17: }

18:  

19: public IService GetService(Type type) { return ... }

   

하지만, 이 방법은 상당히 문제가 많은 방법입니다. 가장 즐겨쓰고, 흔히 볼 수 있는 Pattern 이기 때문에 추가되는 Factory 마다 객체 등을 Factory Provider 에 등록을 해 주어야 합니다. 그 뿐만이 아니죠. Factory Pattern 의 특성상 객체를 생성하는 Factory 는 일일이 각 객체의 타입을 체크하여 반환해 주어야 합니다.

그리고 위의 코드에서는 Type 인자가 1개이지만, 그 이상이라면??? 가령, Generic Type Class<T1,T2,T3,T4,T5> 가 된다면 대략 난감하겠죠. 일단 작은 코드에서는 쓸만할 수 있지만, 꾸준히 성장하는 코드라면 이러한 Factory 방식은 코드의 변경이 너무 잦아집니다.

   

두 번째 방법 - Type Mapping

MEF 는 Codeplex 에 공개가 되어있고, MEF Contrib 으로 불리우는 MEF 의 확장 라이브러리 입니다. MEF Contrib 의 가장 큰 특징 중에 하나인 ComposablePartCatalog 를 재정의 하는 Generic Catalog 를 지원해 줍니다. 이 링크에서 Type Mapping 을 통한 문서를 볼 수 있습니다.

public class GenericCatalogContext
{
protected AggregateCatalog _aggegateCatalog;
protected GenericCatalog _genericCatalog;
protected ImportDefinition _repositoryImportDefinition;

public GenericCatalogContext()
{
var typeCatalog = new TypeCatalog(typeof(OrderProcessor), typeof(RepositoryTypeLocator));
_aggegateCatalog =
new AggregateCatalog();
_aggegateCatalog.Catalogs.Add(typeCatalog);
_genericCatalog =
new GenericCatalog(_aggegateCatalog);
string orderProcessorContract = AttributedModelServices.GetContractName(typeof(OrderProcessor));
var orderProcessPartDefinition = typeCatalog.Parts.Single(p => p.ExportDefinitions.Any(d => d.ContractName == orderProcessorContract));
_repositoryImportDefinition = orderProcessPartDefinition.ImportDefinitions.First();
Context();
}

public virtual void Context()
{

}
}

[InheritedExport]
public abstract class GenericContractTypeMapping
{
public GenericContractTypeMapping(Type genericContractTypeDefinition, Type genericImplementationTypeDefinition)
{
}

public Type GenericContractTypeDefinition { get; }
public Type GenericImplementationTypeDefinition { get; }
}

public class RepositoryTypeLocator : GenericContractTypeMapping
{
public RepositoryTypeLocator()
:
base(typeof(IRepository<>), typeof(Repository<>))
{
}
}

public class Repository<T> : IRepository<T>
{
}

이러이러한 과정을 통해서 아래와 같이 Type Mapping 을 통해 Generic Type 을 사용할 수 있습니다.

[TestFixture]
public class When_querying_catalog_for_an_order_repository_and_no_closed_repository_is_present : GenericCatalogContext
{
[Test]
public void order_repository_part_definition_is_created()
{
Assert.IsNotNull(_result.Item1);
}

[Test]
public void order_repository_export_is_created()
{
Assert.IsNotNull(_result.Item2);
}

public override void Context()
{
_result = _genericCatalog.GetExports(_repositoryImportDefinition).Single();
}

private Tuple<ComposablePartDefinition, ExportDefinition> _result;
}

Contract Type 와 Mapping Type 을 매핑하여 Locator 로 등록하여 주고, 각각 Mapping Class 를 통해 실제 계약의 Generic Type 매핑이 이루어 집니다.

다시 말해서, Generic Class 별로 Locator Class, Mapping Class, 그리고 Mapping Context Class 를 만들어주어야 합니다. 배보다 배꼽이 더 커지는 격입니다. 일단, 아이디어는 좋지만 안쓰고 말랍니다.

   

세 번째 방법 - MEF + Unity 조합

아마도 가장 이상적인 방법이긴 합니다. Unity Application Block 은 Unity Container Extension 을 지원하기 때문에 객체의 Register, Resolve 등의 이벤트를 가로채서 Unity 의 기능을 확장할 수 있습니다. 이 이벤트를 MEF 에서 받도록 하여 MEF 의 ExportProvider 의 GetExportsCore 를 통해 Unity 의 객체에서 Resolve 하도록 하는 방법입니다.

UnityContainerExtension 을 재정의하여, 아래와 같이 이벤트를 받고, 이것을 MEF ExportProvider 로 전달하는 방법입니다.

UnityContainerExntension 에서는 아래와 같이...

protected override void Initialize()
{
this.Context.Registering += new EventHandler<RegisterEventArgs>(Context_Registering);
this.Context.RegisteringInstance += new EventHandler<RegisterInstanceEventArgs>(Context_RegisteringInstance);
}

MEF 의 ExportProvider 에서는 아래와 같이…

protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
{
if (definition.ContractName != null)
{
Type contractType;
if(Mapping.TryGetValue(definition.ContractName, out contractType))
{
if (definition.Cardinality == ImportCardinality.ExactlyOne || definition.Cardinality == ImportCardinality.ExactlyOne)
{
var export = new Export(definition.ContractName, () => serviceLocator.GetInstance(contractType));
return new List<Export> { export };
}

}
}
return Enumerable.Empty<Export>();
}

일단 가장 완벽해 보입니다만, 이 속에는 그 이상 많은 문제들이 생기게 됩니다. MEF 도 내부적으로 Injection(주입) 기법을 사용하고, Unity 에서도 Injection 을 사용하는데 바로 이 Injection 방법이 달라지게 되는 것입니다. 즉, MEF 기반의 코드와 Unity 기반의 코드의 Injection 선언 방법이 틀려지고, 서로 호환할 수 없다는 것입니다.

결국 DI 프레임워크는 특정 DI Container 에 의존할 수 밖에 없어지고, 더불어 Compisite 과 Injection 은 두 가지의 사용 방법이 혼재될 수 밖에 없다는 것이죠.

   

Conclusion

MEF 에서 Generic Type 을 사용하고 싶어서 안달이 난 1은 여러 가지 방법을 찾아보았지만, 사용성, 재사용성, 확장성, 유연성 등 모든 면에서 원하는 해답을 찾지 못했습니다. 그리고 현재까지 MEF 에서 Generic Type 을 지원하기 위한 대략적인 3가지 방법을 정리해보도록 하죠.

  

장점

단점

MEF Factory Export Provider

  • 구현이 쉽다
  • Factory 의 관리가 힘들다
  • Factory 의 확장이 힘들다
  • 모든 Factory 를 Catalog 로 관리해야 한다.

MEF Contrib Type Mapping

  • 합리적이다
  • Type Mapping 코드가 복잡하다
  • Mapping/Locator/Context 클래스를 구현해야 한다
  • 상속 기반이다

MEF + Unity Integrated

  • 합리적이고 , 구현이 쉽다
  • Injection 기법이 서로 달라진다
  • Injection 코드가 서로 달라진다
  • Injection 이 호환되지 않는다
  • 각각의 객체간의 Composite 이 불가능하다

이제 슬슬 머리가 아파옵니다. 향후 .NET Framework 4.0 에서 가장 큰 빛을 보게 될 MEF 이지만, Generic Type 을 지원하지 않는다는 것은 가장 큰 오점이 아닐까 생각합니다. 우선 이쯤에서 마무리하고 어떻게 해야 할지 생각해 보도록 하지요.


MEF 에서 Generic Type 문제는 코드 플랙스에 MEFGeneric 으로 공개하였습니다.
[.NET/.NET Framework] - MEFGeneric 코드 플랙스에 공개합니다.

저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License

댓글을 달아 주세요

Posted by 엄준일(땡초)

.NET Framework 4.0 에 포함이 될 Managed Extensibility Framework(이하 MEF) 는 Generic Type 을 지원하지 않습니다. ( MEF is not supporting Generic Type!!!! )   

상당히 충격입니다. MEF 는 현재 Generic Type 을 지원하지 않습니다. 이것을 가지고 현재 중요한 프로젝트를 진행하기 위해 여러 가지 리뷰를 해 보고 있습니다만, MEF 가 Generic Type 을 지원하지 않는 것은 쉽게 말해 'MEF 는 아직…' 이라는 결론이 나는군요.    


Managed Extensibility Framework Basic

이것을 이해하기 위해서는 MEF 의 기본부터 이해해야 할 필요가 있습니다. 자세한 내용은 아래의 필자의 블로그 링크를 클릭하시면 Managed Extensibility Framework 에 대한 아티클을 볼 수 있습니다.

우선 이러한 원인은 MEF 가 Contract Model(계약 모델) 기반이라는 있다는 이유 입니다. 우리가 흔히 사용하는 계약 모델은 쉽게 이야기하면 제공자와 소비자로 구분할 수 있습니다. 제공자와 소비자의 거래가 성립이 되기 위해서는 바로 계약이라는 것이 필요하죠. MEF 로 비유하자만 Import/Export 가 바로 그것이며 그 계약을 성립시켜 주는 것이 MEF Container 와 Composition Batch 로 볼 수 있습니다.

바로 이러한 계약 기반과 Composable Part 라는 개념으로 기존의 컴포넌트의 재사용성을 높일 수 있게 되며, 좀 더 동적이며, 추상화가 가능한 프레임워크 입니다. 더 쉽게 얘기하면, 새로운 C 라는 컴포넌트는 A 와 B 라는 컴포넌트와 계약하여 결합시키거나, 기존 컴포넌트를 변형시키는 등 Composable Application 을 만들기 위해 계약의 명세만 알면 다양한 컴포넌트를 재생산, 변형, 다양성, 재활용 등을 할 수 있습니다.

 

MEF 는 내부적으로 이러한 명확한 계약을 위해 여러 가지 방법으로 계약을 정의할 수 있습니다. 기본적으로 ExportAttribute 을 사용하여 String, CLR Type, ExportMetadata 를 사용하게 되어 있지요. 하지만 MEF 는 모든 계약의 명세는 바로 String 을 사용하는 데에서 문제가 발생하게 됩니다. 그리고 이것이 Dependency Injection(DI) 와 Inversion Of Control(IoC) 와 다른 점입니다. 대부분의 DI 프레임워크는 Object 의 Lifecycle 을 관리하고 객체의 의존성을 낮추기 위해 역제어 하는 것에 초점이 맞추어져 있기 때문에 CLR Type 기반으로 Container 에 등록이 됩니다.

예를 들어 보면, 아래와 같은 것이 MEF 에서는 계약 명세 규격에 어긋난다는 의미입니다. (특정 DI 프레임워크에 종속되지 않는 코드입니다)

var container = new Container();
container.Register<IUMC<>>();

var obj = container.Resolve<IUMC<string>>();
obj.SayHello();

   

Why MEF is not supporting Generic Type?

MEF 가 Generic Type 을 지원하지 않는 것에 이미 많은 사람들이 문제를 발견했고, 몇 가지 해결 방법이 있긴 있습니다.

이미 Ayende Rahien 이라는 사람의 블로그에는 MEF 가 Generic Type 을 지원하지 않는 것에 대한 이야기를 합니다. 내용을 보면 처음부터 Microsoft 의 MEF 개발 팀은 Generic Type 을 배제하고 있었던 것 같습니다. 하지만 Ayende Rahien 씨는 이 문제에 대해 반드시 해결해야 한다는 이야기를 MEF 개발 팀과 나누었습니다. 저도 이 문제가 반드시 해결 되리라 생각합니다만… 현재로써는 글쎄 ^^;

여기에서 MEF 개발 팀은 조금 구차한 변명을 합니다. 위에서 얘기한 MEF 의 기본은 계약 기반의 프레임워크라는 것입니다. 이 문제에 대해 추측을 해보면, MEF 가 Generic Type 을 지원한다는 것은 Strongly Contract Based 가 될 수 없기 때문이고, Generic Type 으로 인해 명확한 계약이 이루어질 수 없다는 것입니다. 특히 MEF 는 계약의 명세가 모두 MEF 가 내부적으로 관리하고 있기 때문에, Generic Type 에 의한 객체 의 계약 관리는 엄청난 메모리 사용량을 증가로 이어질 가능성이 충분합니다.

실제로 Microsoft 에서 MEF 개발 팀의 PM 을 맡고 있는 Glenn Block 씨는 이 아티클에서는 MEF v1 에서는 Generic Type 을 지원하지 못할 것이라고 합니다. 만약에 Generic Type 을 지원하게 된다면 차기 버전이 될 듯 합니다.

하지만, 다시 한번 MEF 는 계약 기반의 모델이라는 것을 생각하지 않을 수 없습니다. 만약 계약이 명확하지 않다면 계약 자체가 불명확하다는 의미입니다. C# 2.0 부터 지원하는 Generic Type 의 명확하지 않는 타입이 계약에 존재한다면 이것은 계약 자체가 성립되기 힘들다는 전제 조건을 포함하게 됩니다.

MEF 의 예를 들어 봅시다. 아래와 같은 Generic Type 의 계약이 존재합니다. (현재의 MEF 로는 전혀 불가능한 코드입니다^^;)

public interface IUMC<T>
{

void SayHello<T>();
}

[Export(typeof(IUMC<>))]
public class UMC<T> : IUMC<T>
{
public void SayHello()
{
// TODO Impl...
}
}

CLR(Common Language Runtime) 의 Generic Type 의 특성상 Generic T Parameter 는 굉장히 다형적입니다. UMC<string> 또는 UMC<int> 또는 모든 Class Type 이 T Parameter 에 대입될 수 있습니다. 단순히 어떤 타입도 올 수 있다는 것을 떠나 물건을 팔 사람은 도대체 소비자가 누구와 계약한 것인지 알 수 없고, 실제 상거래와 같은 상황이라면 사기와도 같다는 것이죠. 굳이 예를 들자면, 주민등록번호가 다름에도 불구하고, 주민등록증의 이름이 같은 동명인에게 언제든지 계약을 할 수 있다는 것이죠.

DI(Dependency Injection / IoC) 는 CLR Type 을 기반으로 합니다. 일부 DI 프레임워크는 Tag 와 같은 Contract Data 를 제공하기는 하지만 이것은 Metadata 그 이상의 역활을 하지 않습니다. 즉 Contract(계약) 와는 전혀 무관하다는 이야기 입니다. 객체를 질의(Query) 하기 위함이지 Composable 을 위한 것은 아닙니다.

 

OK! I'm understand. But…!!

처음부터 MEF 는 계약 기반의 Composable/Plugin Model/Contract Based 라는 용어를 자주 만나게 됩니다. 그리고 계약 자체라는 의미에서 Generic Type 은 가장 큰 장애 요소임이 확실합니다. 그렇기 때문에 현존하는 모든 DI(Dependency Injection) 프레임워크는 계약(Contract) 라는 용어를 절대 사용하지 않습니다. 목적 자체가 계약과는 전혀 무관하기 때문입니다.

하지만, MEF 의 계약 모델은 내부적으로 String Based Contract 를 사용하고 있고, Generic Type 또한 String 으로 표현이 가능하기 때문에, 문자열의 Parsing 만으로 어느 정도의 Generic Type 을 지원할 수 있을 거라고 생각했습니다.

필자는 처음 MEF 를 본 순간 "이것을 물건이다!" 라는 걸 느꼈습니다만, 아마도 MEF 개발 팀은 두 가지의 고민을 했을 거라고 생각합니다. Silverlight 를 지원할지, Generic Type 을 지원할지에 대한 범용성에 대해서 말입니다. 하지만, Generic 에 대해 많은 피드백을 받음에도 불구하고 MEF v1 에 지원하지 않을 듯한 대답은 사실 "구차한 변명" 으로 밖에 들리지 않는답니다. 결국, 현재 MEF 는 Silverlight 를 지원하는 등 .NET Framework 의 범용성에 치중하였고, 결국 Generic Type 은 현재 시점에서 릴리즈 시점까지 구현이 불가능할 거라고 예상합니다.

아쉽긴 하지만, 현재 MEF 가 불가능한 Generic Type 에 대한 영역은 몇 가지 Open Source 에서 제공을 하고 있습니다. 단지 실제 사용성에 대한 의구심과 필자의 견해로는 안쓰는게 나을 것 같다는 판단입니다.

다음에 당장 지원하지 않는 Generic Type 을 어떻게 사용할지 알아보고 함께 돌파구를 찾아보도록 하겠습니다. 


MEF 에서 Generic Type 문제는 코드 플랙스에 MEFGeneric 으로 공개하였습니다.
[.NET/.NET Framework] - MEFGeneric 코드 플랙스에 공개합니다.

저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License

댓글을 달아 주세요