2012-12-17 2 views
5

많은 F # 및 C# 프로젝트가있는 솔루션이 있습니다. 필자의 목표는 ILMerge를 사용하여 이들 모두를 하나의 라이브러리에 병합하는 것입니다. 결과로 병합 된 dll은 NuGet 패키지에 저장되고 다른 프로젝트에서 참조됩니다. 그러나 병합 된 DLL이 F # 프로젝트에서 참조 될 때 몇 가지 문제가 있습니다.F # 및 C# 어셈블리를 ILMerge와 병합하여 참조 할 때 모든 유형을 사용할 수있게하는 방법은 무엇입니까?

ILMerge에 제공된 기본 어셈블리가 F #이면 F # 프로젝트에서 결과 dll을 참조하면 F # 유형에만 액세스 할 수 있습니다. C# dll이 병합을위한 기본 어셈블리로 선택된 경우 F # 프로젝트에서 참조 할 때 병합 된 F # 어셈블리의 확장 메서드를 사용할 수 없습니다. AutoOpen 속성이있는 모듈은 더 이상 포함 된 네임 스페이스를 열 때 암시 적으로 열리지 않습니다.

모든 형식 (확장 메서드 포함)을 사용할 수 있도록 F # 및 C# 어셈블리를 병합하는 방법이 있습니까?

+0

답변을 찾았습니까? –

+0

결국 ILMerge를 사용하지 않기로 결정했습니다. 그래서 불행히도 F #과 C# 어셈블리를 성공적으로 병합하는 대답은 없습니다. – Domas

답변

4

코드베이스의 일부에서는 라이브러리의 큰 부분이 F #에서 처리되고 나머지는 C#에서 처리됩니다. F # 코드와 C# 코드 모두 앞면입니다.

echo merging %mergeapp% /keyfile:"%keyfile%" /target:library /attr:"%dstpath%%csharpdll%" /targetplatform:%targetplatform%,%targetlib% /lib:%sllib% /lib:%targetlib% /lib:"%libpath%lib" /out:"%mergedpath%..\%csharpdll%" "%dstpath%%csharpdll%" "%dstpath%%fsharpdll%" 
%mergeapp% /keyfile:"%keyfile%" /target:library /attr:"%dstpath%%csharpdll%" /targetplatform:%targetplatform%,%targetlib% /lib:%sllib% /lib:%targetlib% /lib:"%libpath%lib" /out:"%mergedpath%..\%csharpdll%" "%dstpath%%csharpdll%" "%dstpath%%fsharpdll%" 

을하고 우리가하려는 것을 수행 : 우리는 mergeing의 관심과 내가 볼을 취할 지옥 배치 파일을

우리가이 코드와 합병한다는 것이다. 그러나 우리는 확장 방법을 공개하지 않으며 AutoOpen을 수행하지 않습니다. 우리가 발견 한 것은 F # 컴파일러의 버그였습니다. 난독 화를 시작하기 전까지 F # 어셈블리에서 ildasm을 실행하고 불쾌한 코드를 추출해야했습니다. 다른 문제는 F #이 멤버의 보호 된 한정자를 제대로 지원하지 않기 때문에 (F # 공개), 보호 대상 클래스 멤버에 속할 수있는 특성을 만들었습니다. 그런 다음 우리는 Cecil을 사용하여 어셈블리를 분해하고 속성을 추출하고 보호 대상 멤버에 대한 액세스를 변경하는 도구 (code is in the accepted answer here)를 작성했습니다.

나는에 AutoOpen에 대해 알고하지 않았다,하지만 비슷한 작업을해야했다, 그래서 나는이 같은 작업의 종류했던 등록자라는 클래스를 만들었 : 내 정적 생성자에서 다음

type FSharpRegistrant() = 
    do 
     // do whatever I need to get going 

을 C# 모듈에서 클래스를 찾기 위해 리플렉션을 사용하여 F # 등록자를 인스턴스화하는 코드를 작성했습니다. (내 코드베이스에서는 C# 코드가 먼저 빌드되고 F # 코드는 전혀 모르기 때문에). 이것은 오류 검사가 많은 추악한 코드이지만 작동합니다.

관련 문제