대상 프레임 워크가 최신 버전 인 경우 내 프로젝트의 코드를 대폭 개선 할 수있는 사소한 부분이 있습니다. C #의 조건부 컴파일을 더 잘 활용하여 필요에 따라 전환 할 수 있기를 바랍니다.
다음과 같은 것 :
#if NET40
using FooXX = Foo40;
#elif NET35
using FooXX = Foo35;
#else NET20
using FooXX = Foo20;
#endif
무료로 제공되는 기호가 있습니까? 프로젝트 구성의 일부로 이러한 기호를 삽입해야합니까? MSBuild에서 어떤 프레임 워크가 대상이되는지 알기 때문에 쉽게 할 수 있습니다.
/p:DefineConstants="NET40"
사람들은이 상황을 어떻게 처리하고 있습니까? 다른 구성을 만들고 있습니까? 명령 줄을 통해 상수를 전달하고 있습니까?
답변
이를 수행하는 가장 좋은 방법 중 하나는 프로젝트에서 다른 빌드 구성을 만드는 것입니다.
<PropertyGroup Condition=" '$(Framework)' == 'NET20' ">
<DefineConstants>NET20</DefineConstants>
<OutputPath>bin\$(Configuration)\$(Framework)</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Framework)' == 'NET35' ">
<DefineConstants>NET35</DefineConstants>
<OutputPath>bin\$(Configuration)\$(Framework)</OutputPath>
</PropertyGroup>
그리고 기본 구성 중 하나에서 :
<Framework Condition=" '$(Framework)' == '' ">NET35</Framework>
다른 곳에서 정의되지 않은 경우 기본값을 설정합니다. 위의 경우 OutputPath는 각 버전을 빌드 할 때마다 별도의 어셈블리를 제공합니다.
그런 다음 AfterBuild 대상을 만들어 다른 버전을 컴파일합니다.
<Target Name="AfterBuild">
<MSBuild Condition=" '$(Framework)' != 'NET20'"
Projects="$(MSBuildProjectFile)"
Properties="Framework=NET20"
RunEachTargetSeparately="true" />
</Target>
이 예제는 첫 번째 빌드 후에 Framework 변수를 NET20으로 설정하여 전체 프로젝트를 다시 컴파일합니다 (둘 다 컴파일하고 첫 번째 빌드가 위에서 기본 NET35라고 가정). 각 컴파일에는 조건부 정의 값이 올바르게 설정됩니다.
이러한 방식으로 파일을 #ifdef 할 필요없이 프로젝트 파일에서 특정 파일을 제외 할 수도 있습니다.
<Compile Include="SomeNet20SpecificClass.cs" Condition=" '$(Framework)' == 'NET20' " />
또는 참조
<Reference Include="Some.Assembly" Condition="" '$(Framework)' == 'NET20' " >
<HintPath>..\Lib\$(Framework)\Some.Assembly.dll</HintPath>
</Reference>
답변
지금까지 나를 위해 일하는 대안은 프로젝트 파일에 다음을 추가하는 것입니다.
<PropertyGroup>
<DefineConstants Condition=" !$(DefineConstants.Contains(';NET')) ">$(DefineConstants);$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</DefineConstants>
<DefineConstants Condition=" $(DefineConstants.Contains(';NET')) ">$(DefineConstants.Remove($(DefineConstants.LastIndexOf(";NET"))));$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</DefineConstants>
</PropertyGroup>
“v3.5″와 같은 TargetFrameworkVersion 속성의 값을 사용하여 “v”및 “.”를 대체합니다. “NET35″를 얻으려면 (새 속성 함수 기능 사용) 그런 다음 기존 “NETxx”값을 제거하고이를 DefinedConstants 끝에 추가합니다. 이것을 능률화하는 것이 가능할 수도 있지만 나는 바이올린을 켤 시간이 없습니다.
VS에서 프로젝트 속성의 빌드 탭을 보면 조건부 컴파일 기호 섹션에 결과 값이 표시됩니다. 애플리케이션 탭에서 대상 프레임 워크 버전을 변경하면 기호가 자동으로 변경됩니다. 그런 다음 #if NETxx
일반적인 방법으로 전 처리기 지시문 을 사용할 수 있습니다 . VS에서 프로젝트를 변경해도 사용자 정의 PropertyGroup이 손실되지 않는 것 같습니다.
이것은 Client Profile 대상 옵션에 대해 다른 것을주는 것 같지 않지만 나에게는 문제가되지 않습니다.
답변
초기 상수가 이러한 속성에 의해 미리 만들어 졌기 때문에 이러한 솔루션에 문제가있었습니다.
<DefineConstants />
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<DebugSymbols>true</DebugSymbols>
Visual Studio 2010은 세미콜론으로 인해 잘못된 문자라고 주장하는 오류도 발생했습니다. 오류 메시지는 쉼표로 구분 된 미리 빌드 된 상수를 볼 수 있었고 결국 “불법”세미콜론이 뒤 따르는 것을 볼 수 있었기 때문에 힌트를주었습니다. 약간의 재 포맷 및 마사지 후 저에게 맞는 솔루션을 찾을 수있었습니다.
<PropertyGroup>
<!-- Adding a custom constant will auto-magically append a comma and space to the pre-built constants. -->
<!-- Move the comma delimiter to the end of each constant and remove the trailing comma when we're done. -->
<DefineConstants Condition=" !$(DefineConstants.Contains(', NET')) ">$(DefineConstants)$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", "")), </DefineConstants>
<DefineConstants Condition=" $(DefineConstants.Contains(', NET')) ">$(DefineConstants.Remove($(DefineConstants.LastIndexOf(", NET"))))$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", "")), </DefineConstants>
<DefineConstants Condition=" $(TargetFrameworkVersion.Replace('v', '')) >= 2.0 ">$(DefineConstants)NET_20_OR_GREATER, </DefineConstants>
<DefineConstants Condition=" $(TargetFrameworkVersion.Replace('v', '')) >= 3.5 ">$(DefineConstants)NET_35_OR_GREATER</DefineConstants>
<DefineConstants Condition=" $(DefineConstants.EndsWith(', ')) ">$(DefineConstants.Remove($(DefineConstants.LastIndexOf(", "))))</DefineConstants>
</PropertyGroup>
고급 컴파일러 설정 대화 상자의 스크린 샷을 게시합니다 (프로젝트의 컴파일 탭에서 “고급 컴파일 옵션 …”버튼을 클릭하여 열림). 그러나 새로운 사용자로서 나는 그렇게 할 담당자가 부족합니다. 스크린 샷을 볼 수 있다면 속성 그룹에 의해 자동으로 채워지는 사용자 지정 상수가 표시되고 “그 중 일부를 가져와야합니다.”라고 말할 것입니다.
편집 : 그 담당자는 놀랍도록 빠르게 .. 감사합니다! 그 스크린 샷은 다음과 같습니다.
답변
상수 지우기로 시작하십시오.
<PropertyGroup>
<DefineConstants/>
</PropertyGroup>
다음으로 디버그, 추적 및 다음과 같은 기타 상수를 빌드하십시오.
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>TRACE;DEBUG;$(DefineConstants)</DefineConstants>
</PropertyGroup>
마지막으로 프레임 워크 상수를 빌드합니다.
<PropertyGroup Condition=" '$(TargetFrameworkVersion)' == 'v2.0' ">
<DefineConstants>NET10;NET20;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFrameworkVersion)' == 'v3.0' ">
<DefineConstants>NET10;NET20;NET30;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFrameworkVersion)' == 'v3.5' ">
<DefineConstants>NET10;NET20;NET30;NET35;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFrameworkVersion)' == 'v4.0' ">
<DefineConstants>NET10;NET20;NET30;NET35;NET40;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFrameworkVersion)' == 'v4.5' ">
<DefineConstants>NET10;NET20;NET30;NET35;NET40;NET45;$(DefineConstants)</DefineConstants>
</PropertyGroup>
이 접근 방식은 매우 읽기 쉽고 이해하기 쉽습니다.
답변
.csproj 파일에서 기존 <DefineConstants>DEBUG;TRACE</DefineConstants>
줄 뒤에 다음을 추가합니다.
<DefineConstants Condition=" '$(TargetFrameworkVersion.Replace("v",""))' >= '4.0' ">NET_40_OR_GREATER</DefineConstants>
<DefineConstants Condition=" '$(TargetFrameworkVersion.Replace("v",""))' == '4.0' ">NET_40_EXACTLY</DefineConstants>
디버그 및 릴리스 빌드 구성 모두에 대해이 작업을 수행하십시오. 그런 다음 코드에서 사용하십시오.
#if NET_40_OR_GREATER
// can use dynamic, default and named parameters
#endif
답변
@Azarien, 귀하의 답변은 Jeremy와 결합하여 Debug | Release 등이 아닌 한곳에 보관할 수 있습니다.
저에게는 두 변형을 결합하는 것이 가장 잘 작동합니다. 즉 #if NETXX를 사용하여 코드에 조건을 포함하고 한 번에 여러 프레임 워크 버전을 빌드하는 것입니다.
내 .csproj 파일에 다음이 있습니다.
<PropertyGroup>
<DefineConstants Condition=" '$(TargetFrameworkVersion.Replace("v",""))' >= '4.0' ">NET_40_OR_GREATER</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFrameworkVersion.Replace("v",""))' == '3.5' ">
<DefineConstants>NET35</DefineConstants>
<OutputPath>bin\$(Configuration)\$(TargetFrameworkVersion)</OutputPath>
</PropertyGroup>
및 대상 :
<Target Name="AfterBuild">
<MSBuild Condition=" '$(TargetFrameworkVersion.Replace("v",""))' >= '4.0' "
Projects="$(MSBuildProjectFile)"
Properties="TargetFrameworkVersion=v3.5"
RunEachTargetSeparately="true" />
</Target>
답변
.NET Core 빌드 시스템을 사용하는 경우 미리 정의 된 기호를 사용할 수 있습니다 (실제로 이미 예제와 일치하며 변경할 필요가 없습니다 .csproj
!).
#if NET40
using FooXX = Foo40;
#elif NET35
using FooXX = Foo35;
#else NET20
using FooXX = Foo20;
#endif
미리 정의 된 기호 목록은 크로스 플랫폼 도구 및 #if (C # 참조)를 사용 하여 라이브러리 개발에 설명되어 있습니다 .
.NET 프레임 워크 :
NETFRAMEWORK
,NET20
,NET35
,NET40
,NET45
,NET451
,NET452
,NET46
,NET461
,NET462
,NET47
,NET471
,NET472
,NET48
.NET 표준 :
NETSTANDARD
,NETSTANDARD1_0
,NETSTANDARD1_1
,NETSTANDARD1_2
,NETSTANDARD1_3
,NETSTANDARD1_4
,NETSTANDARD1_5
,NETSTANDARD1_6
,NETSTANDARD2_0
,NETSTANDARD2_1
.NET 코어 :
NETCOREAPP
,NETCOREAPP1_0
,NETCOREAPP1_1
,NETCOREAPP2_0
,NETCOREAPP2_1
,NETCOREAPP2_2
,NETCOREAPP3_0