3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // There are cases where we have multiple assemblies that are going to import this file and
8 // if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
9 // that the type is found both in the source and in a referenced assembly. The compiler will prefer
10 // the version of the type defined in the source
12 // In order to disable the warning for this type we are disabling this warning for this entire file.
13 #pragma warning disable 436
16 using System.Collections.Generic;
20 internal static partial class AppContextDefaultValues
22 public static void PopulateDefaultValues()
24 string platformIdentifier, profile;
27 ParseTargetFrameworkName(out platformIdentifier, out profile, out version);
29 // Call into each library to populate their default switches
30 PopulateDefaultValuesPartial(platformIdentifier, profile, version);
34 /// We have this separate method for getting the parsed elements out of the TargetFrameworkName so we can
35 /// more easily support this on other platforms.
37 private static void ParseTargetFrameworkName(out string identifier, out string profile, out int version)
39 string targetFrameworkMoniker = AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName;
41 // If we don't have a TFM then we should default to the 4.0 behavior where all quirks are turned on.
42 if (!TryParseFrameworkName(targetFrameworkMoniker, out identifier, out version, out profile))
45 if (CompatibilitySwitches.UseLatestBehaviorWhenTFMNotSpecified)
47 // If we want to use the latest behavior it is enough to set the value of the switch to string.Empty.
48 // When the get to the caller of this method (PopulateDefaultValuesPartial) we are going to use the
49 // identifier we just set to decide which switches to turn on. By having an empty string as the
50 // identifier we are simply saying -- don't turn on any switches, and we are going to get the latest
51 // behavior for all the switches
52 identifier = string.Empty;
57 identifier = ".NETFramework";
59 profile = string.Empty;
64 // This code was a constructor copied from the FrameworkName class, which is located in System.dll.
65 // Parses strings in the following format: "<identifier>, Version=[v|V]<version>, Profile=<profile>"
66 // - The identifier and version is required, profile is optional
67 // - Only three components are allowed.
68 // - The version string must be in the System.Version format; an optional "v" or "V" prefix is allowed
69 private static bool TryParseFrameworkName(String frameworkName, out String identifier, out int version, out String profile)
71 // For parsing a target Framework moniker, from the FrameworkName class
72 const char c_componentSeparator = ',';
73 const char c_keyValueSeparator = '=';
74 const char c_versionValuePrefix = 'v';
75 const String c_versionKey = "Version";
76 const String c_profileKey = "Profile";
78 identifier = profile = string.Empty;
81 if (frameworkName == null || frameworkName.Length == 0)
86 String[] components = frameworkName.Split(c_componentSeparator);
89 // Identifer and Version are required, Profile is optional.
90 if (components.Length < 2 || components.Length > 3)
96 // 1) Parse the "Identifier", which must come first. Trim any whitespace
98 identifier = components[0].Trim();
100 if (identifier.Length == 0)
105 bool versionFound = false;
109 // The required "Version" and optional "Profile" component can be in any order
111 for (int i = 1; i < components.Length; i++)
113 // Get the key/value pair separated by '='
114 string[] keyValuePair = components[i].Split(c_keyValueSeparator);
116 if (keyValuePair.Length != 2)
121 // Get the key and value, trimming any whitespace
122 string key = keyValuePair[0].Trim();
123 string value = keyValuePair[1].Trim();
126 // 2) Parse the required "Version" key value
128 if (key.Equals(c_versionKey, StringComparison.OrdinalIgnoreCase))
132 // Allow the version to include a 'v' or 'V' prefix...
133 if (value.Length > 0 && (value[0] == c_versionValuePrefix || value[0] == 'V'))
135 value = value.Substring(1);
137 Version realVersion = new Version(value);
138 // The version class will represent some unset values as -1 internally (instead of 0).
139 version = realVersion.Major * 10000;
140 if (realVersion.Minor > 0)
141 version += realVersion.Minor * 100;
142 if (realVersion.Build > 0)
143 version += realVersion.Build;
146 // 3) Parse the optional "Profile" key value
148 else if (key.Equals(c_profileKey, StringComparison.OrdinalIgnoreCase))
150 if (!String.IsNullOrEmpty(value))
169 // This is a partial method. Platforms (such as Desktop) can provide an implementation of it that will read override value
170 // from whatever mechanism is available on that platform. If no implementation is provided, the compiler is going to remove the calls
171 // to it from the code
172 static partial void TryGetSwitchOverridePartial(string switchName, ref bool overrideFound, ref bool overrideValue);
174 /// This is a partial method. This method is responsible for populating the default values based on a TFM.
175 /// It is partial because each library should define this method in their code to contain their defaults.
176 static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version);
180 #pragma warning restore 436