run - visual studio code execute c#
Detectar la versiĆ³n del marco de destino en tiempo de compilaciĆ³n (6)
La pregunta SO vinculada con ''crear N configuraciones diferentes'' es ciertamente una opción, pero cuando tuve una necesidad de esto, simplemente agregué elementos condicionales DefinineConstants, así que en mi Debug | x86 (por ejemplo) después de DefineConstants para DEBUG; TRACE, Agregué estos 2, comprobando el valor en TFV que se estableció en el primer PropertyGroup del archivo csproj.
<DefineConstants Condition=" ''$(TargetFrameworkVersion)'' == ''v4.0'' ">RUNNING_ON_4</DefineConstants>
<DefineConstants Condition=" ''$(TargetFrameworkVersion)'' != ''v4.0'' ">NOT_RUNNING_ON_4</DefineConstants>
No necesitas ambas cosas, obviamente, pero está ahí para dar ejemplos de comportamientos eq y ne - #else y #elif también funcionan bien :)
class Program
{
static void Main(string[] args)
{
#if RUNNING_ON_4
Console.WriteLine("RUNNING_ON_4 was set");
#endif
#if NOT_RUNNING_ON_4
Console.WriteLine("NOT_RUNNING_ON_4 was set");
#endif
}
}
Podría cambiar entre la orientación 3.5 y 4.0 y haría lo correcto.
Tengo un código que hace uso de los Métodos de extensión, pero compila bajo .NET 2.0 usando el compilador en VS2008. Para facilitar esto, tuve que declarar ExtensionAttribute:
/// <summary>
/// ExtensionAttribute is required to define extension methods under .NET 2.0
/// </summary>
public sealed class ExtensionAttribute : Attribute
{
}
Sin embargo, ahora me gustaría que la biblioteca en la que está contenida esa clase también sea compilable bajo .NET 3.0, 3.5 y 4.0, sin la advertencia ''ExtensionAttribute se define en varios lugares''.
¿Hay alguna directiva de tiempo de compilación que pueda usar para incluir solo ExtensionAttribute cuando la versión de framework que se está orientando es .NET 2?
Los grupos de propiedades solo sobrescriben, por lo que esto anularía la configuración de DEBUG
, TRACE
u otros. - Ver la evaluación de propiedad de MSBuild
Además, si la propiedad DefineConstants
se establece desde la línea de comandos, cualquier cosa que se haga dentro del archivo del proyecto es irrelevante ya que esa configuración se convierte en global de solo lectura. Esto significa que sus cambios a ese valor fallan silenciosamente.
Ejemplo de mantenimiento de constantes definidas existentes:
<CustomConstants Condition=" ''$(TargetFrameworkVersion)'' == ''v2.0'' ">V2</CustomConstants>
<CustomConstants Condition=" ''$(TargetFrameworkVersion)'' == ''v4.0'' ">V4</CustomConstants>
<DefineConstants Condition=" ''$(DefineConstants)'' != '''' And ''$(CustomConstants)'' != '''' ">$(DefineConstants);</DefineConstants>
<DefineConstants>$(DefineConstants)$(CustomConstants)</DefineConstants>
Esta sección DEBE venir después de cualquier otra constante definida, ya que es poco probable que se configuren de manera aditiva
Solo definí esos 2 porque eso es principalmente lo que me interesa de mi proyecto, mmm.
Ver también: Propiedades comunes del proyecto MsBuild
Los símbolos predefinidos para los marcos de destino ahora están integrados en la versión de MSBuild que utilizan la herramienta de dotnet
y VS 2017 en adelante. Consulte https://docs.microsoft.com/en-us/dotnet/standard/frameworks#how-to-specify-target-frameworks para obtener la lista completa.
#if NET47
Console.WriteLine("Running on .Net 4.7");
#elif NETCOREAPP2_0
Console.WriteLine("Running on .Net Core 2.0");
#endif
Me gustaría contribuir con una respuesta actualizada que resuelva algunos problemas.
Si configura DefineConstants en lugar de CustomConstants terminará, en la línea de comandos Debug de Conditional Compilation, después de algún cambio de versión de framework, con constantes condicionales duplicadas (es decir: NETFX_451; NETFX_45; NETFX_40; NETFX_35; NETFX_30; NETFX_20; NETFX_35; NETFX_30 ; NETFX_20;). Este es el VersionSpecificSymbols.Common.prop que resuelve cualquier problema.
<!--
*********************************************************************
Defines the Compile time symbols Microsoft forgot
Modelled from https://msdn.microsoft.com/en-us/library/ms171464.aspx
*********************************************************************
Author: Lorenzo Ruggeri ([email protected])
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Choose>
<When Condition=" $(TargetFrameworkVersion) == ''v2.0'' ">
<PropertyGroup>
<CustomConstants >$(CustomConstants);NETFX_20</CustomConstants>
</PropertyGroup>
</When>
<When Condition=" $(TargetFrameworkVersion) == ''v3.0'' ">
<PropertyGroup>
<CustomConstants >$(CustomConstants);NETFX_30</CustomConstants>
<CustomConstants >$(CustomConstants);NETFX_20</CustomConstants>
</PropertyGroup>
</When>
<When Condition=" $(TargetFrameworkVersion) == ''v3.5'' ">
<PropertyGroup>
<CustomConstants >$(CustomConstants);NETFX_35</CustomConstants>
<CustomConstants >$(CustomConstants);NETFX_30</CustomConstants>
<CustomConstants >$(CustomConstants);NETFX_20</CustomConstants>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<CustomConstants Condition="$([System.Version]::Parse(''$(TargetFrameworkVersion.Substring(1))'').CompareTo($([System.Version]::Parse(''4.5.1'')))) >= 0">$(CustomConstants);NETFX_451</CustomConstants>
<CustomConstants Condition="$([System.Version]::Parse(''$(TargetFrameworkVersion.Substring(1))'').CompareTo($([System.Version]::Parse(''4.5'')))) >= 0">$(CustomConstants);NETFX_45</CustomConstants>
<CustomConstants Condition="$([System.Version]::Parse(''$(TargetFrameworkVersion.Substring(1))'').CompareTo($([System.Version]::Parse(''4.0'')))) >= 0">$(CustomConstants);NETFX_40</CustomConstants>
<CustomConstants Condition="$([System.Version]::Parse(''$(TargetFrameworkVersion.Substring(1))'').CompareTo($([System.Version]::Parse(''3.5'')))) >= 0">$(CustomConstants);NETFX_35</CustomConstants>
<CustomConstants Condition="$([System.Version]::Parse(''$(TargetFrameworkVersion.Substring(1))'').CompareTo($([System.Version]::Parse(''3.0'')))) >= 0">$(CustomConstants);NETFX_30</CustomConstants>
<CustomConstants Condition="$([System.Version]::Parse(''$(TargetFrameworkVersion.Substring(1))'').CompareTo($([System.Version]::Parse(''2.0'')))) >= 0">$(CustomConstants);NETFX_20</CustomConstants>
</PropertyGroup>
</Otherwise>
</Choose>
<PropertyGroup>
<DefineConstants>$(DefineConstants);$(CustomConstants)</DefineConstants>
</PropertyGroup>
</Project>
Tengo algunas sugerencias para mejorar las respuestas dadas hasta ahora:
Use Version.CompareTo (). Las pruebas de igualdad no funcionarán para versiones posteriores del framework, que aún no se han nombrado. P.ej
<CustomConstants Condition=" ''$(TargetFrameworkVersion)'' == ''v4.0'' ">
no coincidirá con v4.5 o v4.5.1, lo que normalmente desea.
Use un archivo de importación para que estas propiedades adicionales solo tengan que definirse una vez. Recomiendo mantener el archivo de importación bajo control de fuente, para que los cambios se propaguen junto con los archivos del proyecto, sin esfuerzo adicional.
Agregue el elemento de importación al final de su archivo de proyecto, para que sea independiente de cualquier grupo de propiedades específico de la configuración. Esto también tiene el beneficio de requerir una sola línea adicional en su archivo de proyecto.
Aquí está el archivo de importación (VersionSpecificSymbols.Common.prop)
<!--
******************************************************************
Defines the Compile time symbols Microsoft forgot
Modelled from https://msdn.microsoft.com/en-us/library/ms171464.aspx
*********************************************************************
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DefineConstants Condition="$([System.Version]::Parse(''$(TargetFrameworkVersion.Substring(1))'').CompareTo($([System.Version]::Parse(''4.5.1'')))) >= 0">$(DefineConstants);NETFX_451</DefineConstants>
<DefineConstants Condition="$([System.Version]::Parse(''$(TargetFrameworkVersion.Substring(1))'').CompareTo($([System.Version]::Parse(''4.5'')))) >= 0">$(DefineConstants);NETFX_45</DefineConstants>
<DefineConstants Condition="$([System.Version]::Parse(''$(TargetFrameworkVersion.Substring(1))'').CompareTo($([System.Version]::Parse(''4.0'')))) >= 0">$(DefineConstants);NETFX_40</DefineConstants>
<DefineConstants Condition="$([System.Version]::Parse(''$(TargetFrameworkVersion.Substring(1))'').CompareTo($([System.Version]::Parse(''3.5'')))) >= 0">$(DefineConstants);NETFX_35</DefineConstants>
<DefineConstants Condition="$([System.Version]::Parse(''$(TargetFrameworkVersion.Substring(1))'').CompareTo($([System.Version]::Parse(''3.0'')))) >= 0">$(DefineConstants);NETFX_30</DefineConstants>
</PropertyGroup>
</Project>
Agregar elemento de importación al archivo de proyecto
Refiéralo desde su archivo .csproj agregando al final, antes de la etiqueta.
…
<Import Project="VersionSpecificSymbols.Common.prop" />
</Project>
Tendrá que arreglar la ruta para que apunte a la carpeta común / compartida donde puso este archivo.
Para usar los símbolos de tiempo de compilación
namespace VersionSpecificCodeHowTo
{
using System;
internal class Program
{
private static void Main(string[] args)
{
#if NETFX_451
Console.WriteLine("NET_451 was set");
#endif
#if NETFX_45
Console.WriteLine("NET_45 was set");
#endif
#if NETFX_40
Console.WriteLine("NET_40 was set");
#endif
#if NETFX_35
Console.WriteLine("NETFX_35 was set");
#endif
#if NETFX_30
Console.WriteLine("NETFX_30 was set");
#endif
#if NETFX_20
Console.WriteLine("NETFX_20 was set");
#else
The Version specific symbols were not set correctly!
#endif
#if DEBUG
Console.WriteLine("DEBUG was set");
#endif
#if MySymbol
Console.WriteLine("MySymbol was set");
#endif
Console.ReadKey();
}
}
}
Un ejemplo común de "vida real"
Implementando Join (string delimiter, IEnumerable strings) Antes de .NET 4.0
// string Join(this IEnumerable<string> strings, string delimiter)
// was not introduced until 4.0. So provide our own.
#if ! NETFX_40 && NETFX_35
public static string Join( string delimiter, IEnumerable<string> strings)
{
return string.Join(delimiter, strings.ToArray());
}
#endif
Referencias
Evaluación de propiedad de MSBuild
¿Puedo hacer que una directiva de preprocesador dependa de la versión de .NET Framework?
Use la reflexión para determinar si la clase existe. Si lo hace, entonces cree y use dinámicamente , de lo contrario use la clase de solución .Net2 que se puede definir, pero que no se usa para todas las otras versiones .net.
Aquí está el código que utilicé para una AggregateException
que es .Net 4 y superior solamente:
var aggregatException = Type.GetType("System.AggregateException");
if (aggregatException != null) // .Net 4 or greater
{
throw ((Exception)Activator.CreateInstance(aggregatException, ps.Streams.Error.Select(err => err.Exception)));
}
// Else all other non .Net 4 or less versions
throw ps.Streams.Error.FirstOrDefault()?.Exception
?? new Exception("Powershell Exception Encountered."); // Sanity check operation, should not hit.