@@ -21,6 +21,11 @@ public sealed class OSConditionAttribute : ConditionBaseAttribute
2121#endif
2222#endif
2323
24+ #if NET462
25+ // Cache the detected OS to avoid repeated reflection calls
26+ private static readonly OperatingSystems ? DetectedOS = DetectCurrentOS ( ) ;
27+ #endif
28+
2429 private readonly OperatingSystems _operatingSystems ;
2530
2631 /// <summary>
@@ -51,8 +56,7 @@ public OSConditionAttribute(OperatingSystems operatingSystems)
5156 /// </summary>
5257 public override bool IsConditionMet
5358#if NET462
54- // On .NET Framework, we are sure we are running on Windows.
55- => ( _operatingSystems & OperatingSystems . Windows ) != 0 ;
59+ => DetectedOS is not null && ( _operatingSystems & DetectedOS ) != 0 ;
5660#else
5761 {
5862 get
@@ -79,6 +83,74 @@ public override bool IsConditionMet
7983 }
8084#endif
8185
86+ #if NET462
87+ /// <summary>
88+ /// Detects the current operating system using reflection to maintain compatibility with .NET Framework 4.6.2.
89+ /// </summary>
90+ /// <returns>
91+ /// The detected operating system, or null if the OS could not be determined.
92+ /// </returns>
93+ private static OperatingSystems ? DetectCurrentOS ( )
94+ {
95+ // RuntimeInformation.IsOSPlatform is available in .NET Framework 4.7.1+.
96+ // For older .NET Framework versions or environments where the API is not available,
97+ // we return null to fall back to assuming Windows.
98+ // This also handles Mono which supports RuntimeInformation API and can run on non-Windows platforms.
99+ Type ? runtimeInformationType = Type . GetType ( "System.Runtime.InteropServices.RuntimeInformation, System.Runtime.InteropServices.RuntimeInformation" )
100+ ?? Type . GetType ( "System.Runtime.InteropServices.RuntimeInformation, mscorlib" ) ;
101+ if ( runtimeInformationType is null )
102+ {
103+ return OperatingSystems . Windows ;
104+ }
105+
106+ MethodInfo ? isOSPlatformMethod = runtimeInformationType . GetMethod ( "IsOSPlatform" , BindingFlags . Public | BindingFlags . Static ) ;
107+ if ( isOSPlatformMethod is null )
108+ {
109+ // Fallback to Windows if the method is not found
110+ return OperatingSystems . Windows ;
111+ }
112+
113+ Type ? osPlatformType = Type . GetType ( "System.Runtime.InteropServices.OSPlatform, System.Runtime.InteropServices.RuntimeInformation" )
114+ ?? Type . GetType ( "System.Runtime.InteropServices.OSPlatform, mscorlib" )
115+ ?? throw ApplicationStateGuard . Unreachable ( ) ;
116+
117+ // Use the predefined static properties instead of Create() method
118+ // On Mono, the static properties use uppercase strings (e.g., "LINUX") while Create() uses the provided casing,
119+ // and IsOSPlatform performs case-sensitive comparison against the predefined values.
120+ PropertyInfo ? windowsProp = osPlatformType . GetProperty ( "Windows" , BindingFlags . Public | BindingFlags . Static ) ;
121+ PropertyInfo ? linuxProp = osPlatformType . GetProperty ( "Linux" , BindingFlags . Public | BindingFlags . Static ) ;
122+ PropertyInfo ? osxProp = osPlatformType . GetProperty ( "OSX" , BindingFlags . Public | BindingFlags . Static ) ;
123+ PropertyInfo ? freebsdProp = osPlatformType . GetProperty ( "FreeBSD" , BindingFlags . Public | BindingFlags . Static ) ;
124+
125+ if ( windowsProp != null && IsOSPlatformViaProperty ( isOSPlatformMethod , windowsProp ) )
126+ {
127+ return OperatingSystems . Windows ;
128+ }
129+ else if ( linuxProp != null && IsOSPlatformViaProperty ( isOSPlatformMethod , linuxProp ) )
130+ {
131+ return OperatingSystems . Linux ;
132+ }
133+ else if ( osxProp != null && IsOSPlatformViaProperty ( isOSPlatformMethod , osxProp ) )
134+ {
135+ return OperatingSystems . OSX ;
136+ }
137+ else if ( freebsdProp != null && IsOSPlatformViaProperty ( isOSPlatformMethod , freebsdProp ) )
138+ {
139+ return OperatingSystems . FreeBSD ;
140+ }
141+
142+ // Unknown OS
143+ return null ;
144+ }
145+
146+ private static bool IsOSPlatformViaProperty ( MethodInfo isOSPlatformMethod , PropertyInfo osPlatformProperty )
147+ {
148+ object ? osPlatform = osPlatformProperty . GetValue ( null ) ;
149+ object ? result = isOSPlatformMethod . Invoke ( null , [ osPlatform ] ) ;
150+ return result is true ;
151+ }
152+ #endif
153+
82154 /// <summary>
83155 /// Gets the group name for this attribute.
84156 /// </summary>
0 commit comments