플랫폼 종속 참조를 사용하여 Windows 및 Mac 용 .Net 라이브러리를 만드는 방법이 있습니까?


12

C #을 사용하여 데스크톱 (Windows 및 Mac) 용 크로스 플랫폼 앱을 개발하려고합니다. 이 앱에는 방대한 양의 플랫폼 의존적 인 내용이 포함되어 있으며 팀장은 C #으로 해당 코드를 모두 작성하려고합니다. 이 작업을 수행하는 쉬운 방법은 C ++로 래퍼를 작성하고 C # 코드에서 라이브러리를 참조하고 C ++ 라이브러리가 플랫폼을 처리하게하는 것입니다. 아아, 그렇지 않습니다.

Mac 용 Visual Studio를 사용하여 라이브러리를 설정하려고합니다. 현재 플랫폼의 기본 텍스트 음성 라이브러리에 대한 액세스 권한을 부여하기 위해 단일 라이브러리에서 단일 인터페이스를 제공 할 수 있기를 바랍니다. C # for Windows의 텍스트 음성 변환 라이브러리는 Mac에서 사용할 수 없으므로 실제로 브리지를 제공하는 것 외에 다른 대안이 없습니다.

라이브러리에서 운영 체제 조회를 수행하여 실행중인 운영 체제를 결정하거나 여러 기본 라이브러리를로드하려고 시도하고로드 할 라이브러리를 사용하는 것에 만족합니다.

내가해야한다면, 두 가지 구현을 작성할 수있는 단일 프로젝트가 있어야합니다. Mac 용 Visual Studio에서 라이브러리 프로젝트 를 만드는 방법을 찾지 못했지만 그렇게 할 수는 있습니다. 여러 구현을 허용하는 유일한 프로젝트 유형은 구현이 iOS 또는 Android 용이어야하는 것으로 보입니다.


어떤 .NET 런타임을 사용 하시겠습니까?
Euphoric

2
Xamarin은 비슷한 작업을 수행합니다. 아마도 빌드 구성이 있습니까?
Ewan

2
Mac 용 Visual Studio는 실제로 시각적 인 스튜디오가 아니라 단지 Rebadged Xamarin 스튜디오입니다. 아마도 Xamarin 문서에 뭔가가 있습니까?
richzilla

3
가장 좋은 방법은 서로 다른 어셈블리 일 것입니다. 하나는 인터페이스와 공통 코드 용이고 다른 하나는 대상 플랫폼 용입니다. 그러나 다중 대상을 지정하고 #if 문을 사용하여 구현을 교체 할 수 있습니다. 단점은 활성화되지 않은 것은 평가되지 않으므로 쉽게 최신 정보를 얻을 수 없다는 것입니다.
Berin Loritsch

플랫폼 종속 참조를 말할 때 네이티브 코드 또는 모든 C # 코드를 말하고 있습니까?
Berin Loritsch

답변:


4

좋은 질문이 있습니다. 귀하의 솔루션과 약간의 균형이있을 수 있습니다. 궁극적 인 대답은 실제로 플랫폼에 따른 의미에 따라 다릅니다. 예를 들어, 외부 응용 프로그램을 시작하는 프로세스를 시작하고 단순히 한 응용 프로그램과 다른 응용 프로그램간에 전환하는 경우 너무 복잡하지 않고 처리 할 수 ​​있습니다. 네이티브 라이브러리로 P / Invoke를 사용하고 있다면 약간 더해야 할 일이 있습니다. 그러나 하나의 플랫폼에만있는 라이브러리와 연결하는 경우 여러 어셈블리를 사용해야합니다.

외부 앱

#if이 상황에서 진술 을 사용할 필요는 없습니다 . 일부 인터페이스를 설정하고 플랫폼 당 하나의 구현이 있습니다. 공장을 사용하여 플랫폼을 감지하고 올바른 인스턴스를 제공하십시오.

경우에 따라 특정 플랫폼 용으로 컴파일 된 바이너리 일 뿐이지 만 실행 파일 이름과 모든 매개 변수는 동일하게 정의됩니다. 이 경우 올바른 실행 파일을 해결해야합니다. Windows와 Linux에서 실행할 수있는 대량 오디오 변환기 앱의 경우 바이너리 이름을 확인하는 정적 초기화 프로그램이 있습니다.

public class AudioProcessor
{
    private static readonly string AppName = "lame";
    private static readonly string FullAppPath;

    static AudioProcessor()
    {
        var platform = DetectPlatform();
        var architecture = Detect64or32Bits();

        FullAppPath = Path.combine(platform, architecture, AppName);
    }
}

여기서 멋진 것은 없습니다. 그냥 좋은 ol '유명한 수업.

P / 호출

P / Invoke는 조금 까다 롭습니다. 결론은 올바른 버전의 기본 라이브러리를로드해야한다는 것입니다. Windows에서는 P / Invoke SetDllDirectory()합니다. 다른 플랫폼에서는이 단계가 필요하지 않을 수 있습니다. 그래서 이곳은 일이 지저분해질 수있는 곳입니다. #if특히 배포 패키지에 라이브러리 경로가 포함되어있는 경우 라이브러리 경로 확인을 제어하는 ​​데 사용되는 호출을 제어 하기 위해 명령문 을 사용해야 할 수도 있습니다 .

완전히 다른 플랫폼 종속 라이브러리에 연결

구식 다중 타겟팅 방법이 여기에 유용 할 수 있습니다. 그러나 많은 추악함이 있습니다. 일부 프로젝트가 동일한 DLL 대상 Silverlight, WPF 및 잠재적으로 UAP를 갖도록 시도한 날에는 다른 컴파일 태그를 사용하여 응용 프로그램을 여러 번 컴파일해야합니다. 위의 각 플랫폼의 문제점은 동일한 개념을 공유하지만 플랫폼이 충분히 다르므로 이러한 차이점을 해결해야한다는 것입니다. 우리가 지옥에 들어가는 곳입니다 #if.

이 방법을 사용하려면 .csproj플랫폼 종속 참조를 처리하기 위해 파일을 수동으로 편집해야 합니다. 당신 때문에 .csproj파일이 MSBuild에서 파일, 그것은 알려진하고 예측 가능한 방식으로 할 전적으로 가능하다.

# 지옥이라면

#if명령문을 사용하여 코드 섹션을 켜거나 끌 수 있으므로 애플리케이션 간의 사소한 차이점을 효과적으로 처리 할 수 ​​있습니다. 표면적으로는 좋은 생각처럼 들립니다. 심지어 그리기 상자를 디버깅하기 위해 경계 상자 시각화를 켜고 끄는 수단으로도 사용했습니다.

와 숫자 1 문제 #if가없는 것도 파서에 의해 평가 꺼져 코드. 라이브러리를 재 컴파일하기를 기다리는 잠재적 인 구문 오류 또는 더 나쁜 논리 오류가있을 수 있습니다. 이것은 리팩토링 코드에서 더욱 문제가됩니다. 메소드의 이름을 바꾸거나 매개 변수의 순서를 변경하는 것만 큼 간단한 것은 정상적으로 처리되지만 구문 분석기는 #if명령문에 의해 해제 된 것을 평가하지 않기 때문에 다시 컴파일 할 때까지 볼 수없는 코드가 갑자기 깨졌습니다.

그런 식으로 작성된 모든 디버그 코드는 일련의 리팩토링으로 인해 다시 작성해야했습니다. 다시 쓰는 동안 전역 구성 클래스를 사용하여 해당 기능을 켜고 끕니다. 그것은 도구 증명을 리팩토링했지만 API가 완전히 다른 경우 그러한 솔루션은 도움이되지 않습니다.

내가 선호하는 방법

많은 어려움을 겪은 교훈과 Microsoft 자체의 사례를 기반으로하는 내가 선호하는 방법은 여러 어셈블리를 사용하는 것입니다.

하나의 핵심 NetStandard 어셈블리는 모든 인터페이스를 정의하고 모든 공통 코드를 포함합니다. 플랫폼 종속 구현은 포함 된 경우 기능을 추가하는 별도의 어셈블리에 있습니다.

이 접근 방식은 새로운 구성 API 및 현재 ID 아키텍처로 표시됩니다. 보다 구체적인 통합이 필요하면 새 어셈블리를 추가하기 만하면됩니다. 이러한 어셈블리는 확장 기능을 제공하여 설정에 통합 할 수 있습니다. 의존성 주입 접근 방식을 사용하는 경우 이러한 확장 메소드를 사용하면 라이브러리가 해당 서비스를 등록 할 수 있습니다.

이것은 내가 #if지옥 을 피하고 실질적으로 다른 환경을 만족시키는 유일한 방법에 관한 것입니다.


나는 C # (약 18 년 동안 C ++을 사용했고 약 반나절 동안 C #을 사용 했었습니다.). 이 새로운 구성 API는 ... 그것에 대한 링크를 제공 할 수 있습니까? 나는 그것을 스스로 찾을 수없는 것 같습니다.
Clearer

2
docs.microsoft.com/ko-kr/aspnet/core/fundamentals/configuration/… 추가 구성 소스를 추가하기위한 여러 Nuget 패키지가 있습니다. 예를 들어 환경 변수, JSON 파일 등에서
Berin Loritsch

1
그것은의 Microsoft.Extensions.ConfigurationAPI를 설정합니다.
Berin Loritsch

1
루트 github 프로젝트는 다음과 같습니다. github.com/aspnet/Configuration
Berin Loritsch
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.