internal IEnumerable <RIDMapping> GetRIDMappings() { // base => // Parent yield return(Parent == null ? new RIDMapping(CreateRuntime(BaseRID)) : new RIDMapping(CreateRuntime(BaseRID), new[] { CreateRuntime(Parent) })); foreach (var architecture in Architectures) { // base + arch => // base, // parent + arch var imports = new List <RID>() { CreateRuntime(BaseRID) }; if (!IsNullOrRoot(Parent)) { imports.Add(CreateRuntime(Parent, architecture: architecture)); } yield return(new RIDMapping(CreateRuntime(BaseRID, architecture: architecture), imports)); } RuntimeVersion lastVersion = null; foreach (var version in Versions) { // base + version => // base + lastVersion, // parent + version (optionally) var imports = new List <RID>() { CreateRuntime(BaseRID, version: lastVersion) }; if (ApplyVersionsToParent) { imports.Add(CreateRuntime(Parent, version: version)); } yield return(new RIDMapping(CreateRuntime(BaseRID, version: version), imports)); foreach (var architecture in Architectures) { // base + version + architecture => // base + version, // base + lastVersion + architecture, // parent + version + architecture (optionally) var archImports = new List <RID>() { CreateRuntime(BaseRID, version: version), CreateRuntime(BaseRID, version: lastVersion, architecture: architecture) }; if (ApplyVersionsToParent) { archImports.Add(CreateRuntime(Parent, version: version, architecture: architecture)); } yield return(new RIDMapping(CreateRuntime(BaseRID, version: version, architecture: architecture), archImports)); } if (TreatVersionsAsCompatible) { lastVersion = version; } } foreach (var qualifier in AdditionalQualifiers) { // base + qual => // base, // parent + qual yield return(new RIDMapping(CreateRuntime(BaseRID, qualifier: qualifier), new[] { CreateRuntime(BaseRID), IsNullOrRoot(Parent) ? CreateRuntime(qualifier) : CreateRuntime(Parent, qualifier: qualifier) })); foreach (var architecture in Architectures) { // base + arch + qualifier => // base + qualifier, // base + arch // parent + arch + qualifier var imports = new List <RID>() { CreateRuntime(BaseRID, qualifier: qualifier), CreateRuntime(BaseRID, architecture: architecture) }; if (!IsNullOrRoot(Parent)) { imports.Add(CreateRuntime(Parent, architecture: architecture, qualifier: qualifier)); } yield return(new RIDMapping(CreateRuntime(BaseRID, architecture: architecture, qualifier: qualifier), imports)); } lastVersion = null; foreach (var version in Versions) { // base + version + qualifier => // base + version, // base + lastVersion + qualifier // parent + version + qualifier (optionally) var imports = new List <RID>() { CreateRuntime(BaseRID, version: version), CreateRuntime(BaseRID, version: lastVersion, qualifier: qualifier) }; if (ApplyVersionsToParent) { imports.Add(CreateRuntime(Parent, version: version, qualifier: qualifier)); } yield return(new RIDMapping(CreateRuntime(BaseRID, version: version, qualifier: qualifier), imports)); foreach (var architecture in Architectures) { // base + version + architecture + qualifier => // base + version + qualifier, // base + version + architecture, // base + version, // base + lastVersion + architecture + qualifier, // parent + version + architecture + qualifier (optionally) var archImports = new List <RID>() { CreateRuntime(BaseRID, version: version, qualifier: qualifier), CreateRuntime(BaseRID, version: version, architecture: architecture), CreateRuntime(BaseRID, version: version), CreateRuntime(BaseRID, version: lastVersion, architecture: architecture, qualifier: qualifier) }; if (ApplyVersionsToParent) { imports.Add(CreateRuntime(Parent, version: version, architecture: architecture, qualifier: qualifier)); } yield return(new RIDMapping(CreateRuntime(BaseRID, version: version, architecture: architecture, qualifier: qualifier), archImports)); } if (TreatVersionsAsCompatible) { lastVersion = version; } } } }
public void AddRuntimeIdentifier(RID rid, string parent) { // Do nothing if we already know about the RID if (knownRIDs.Contains(rid)) { return; } RuntimeGroup runtimeGroup = null; if (runtimeGroupsByBaseRID.TryGetValue(rid.BaseRID, out var candidateRuntimeGroups)) { RuntimeVersion closestVersion = null; foreach (var candidate in candidateRuntimeGroups) { if (rid.HasVersion) { // Find the closest previous version foreach (var version in candidate.Versions) { // a previous version if (version <= rid.Version) { // haven't yet found a match or this is a closer match if (closestVersion == null || version > closestVersion) { closestVersion = version; runtimeGroup = candidate; } else if (version == closestVersion) { // found a tie in version, examine other fields considerCandidate(); } } } } // if we don't have a version, or if we couldn't find any match, consider other fields if (!rid.HasVersion) { considerCandidate(); } // if we don't have a match yet, take this as it matches on baseRID runtimeGroup ??= candidate; void considerCandidate() { // is this a better match? if (!rid.HasArchitecture || candidate.Architectures.Contains(rid.Architecture)) { if (!rid.HasQualifier || candidate.AdditionalQualifiers.Contains(rid.Qualifier)) { // matched on arch and qualifier. runtimeGroup = candidate; } else if (rid.HasArchitecture && !runtimeGroup.Architectures.Contains(rid.Architecture)) { // matched only on arch and existing match doesn't match arch runtimeGroup = candidate; } } } } Debug.Assert(runtimeGroup != null, "Empty candidates?"); } else { // This is an unknown base RID, we'll need to add a new group. if (string.IsNullOrEmpty(parent)) { throw new InvalidOperationException($"AdditionalRuntimeIdentifier {rid} was specified, which could not be found in any existing {nameof(RuntimeGroup)}, and no {nameof(parent)} was specified."); } runtimeGroup = new RuntimeGroup(rid.BaseRID, parent); AddRuntimeGroup(runtimeGroup); } runtimeGroup.ApplyRid(rid); // Compute the portion of the RID graph produced from this modified RuntimeGroup var ridMappings = runtimeGroup.GetRIDMappings(); // Record any newly defined RIDs in our set of known RIDs foreach (RID definedRID in ridMappings.Select(mapping => mapping.RuntimeIdentifier)) { knownRIDs.Add(definedRID); } // Make sure that any RID imported is added as well. This allows users to specify // a single new RID and we'll add any new RIDs up the parent chain that might be needed. foreach (RID importedRID in ridMappings.SelectMany(mapping => mapping.Imports)) { // This should not introduce any new RuntimeGroups, so we specify parent as null AddRuntimeIdentifier(importedRID, null); } }