좋은 질문이 있습니다. 귀하의 솔루션과 약간의 균형이있을 수 있습니다. 궁극적 인 대답은 실제로 플랫폼에 따른 의미에 따라 다릅니다. 예를 들어, 외부 응용 프로그램을 시작하는 프로세스를 시작하고 단순히 한 응용 프로그램과 다른 응용 프로그램간에 전환하는 경우 너무 복잡하지 않고 처리 할 수 있습니다. 네이티브 라이브러리로 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
지옥 을 피하고 실질적으로 다른 환경을 만족시키는 유일한 방법에 관한 것입니다.