/// <summary> /// Tries to fulfill the specified <paramref name="demand"/>. Adds the result to <see cref="Selections"/> if successful. /// </summary> /// <returns><c>true</c> if the demand could be met, <c>false</c> if not.</returns> protected bool TryFulfill(SolverDemand demand) { var candidates = GetCompatibleCandidates(demand); var existingSelection = Selections.GetImplementation(demand.Requirements.InterfaceUri); if (existingSelection == null) { // Try to make new selection return(TryFulfill(demand, candidates)); } else { // Try to use existing selection // Ensure existing selection is one of the compatible candidates if (candidates.All(x => x.Implementation.ID != existingSelection.ID)) { return(false); } if (!existingSelection.ContainsCommand(demand.Requirements.Command ?? Command.NameRun)) { // Add additional command to selection if needed var command = existingSelection.AddCommand(demand.Requirements, from: CandidateProvider.LookupOriginalImplementation(existingSelection)); return((command == null) || TryFulfill(DemandsFor(command, demand.Requirements.InterfaceUri))); } return(true); } }
/// <summary> /// Gets all <see cref="SelectionCandidate"/>s for the <paramref name="demand"/> that are compatible with the current <see cref="Selections"/> state. /// </summary> private IEnumerable <SelectionCandidate> GetCompatibleCandidates(SolverDemand demand) => demand.Candidates.Where(candidate => { if (!candidate.IsSuitable) { return(false); } var nativeImplementation = candidate.Implementation as ExternalImplementation; // Ensure the candidate does not conflict with restrictions of existing selections foreach (var restriction in Selections.RestrictionsFor(demand.Requirements.InterfaceUri)) { // Prevent mixing of 32-bit and 64-bit binaries if (candidate.Implementation.Architecture.Cpu.Is32Bit() && Selections.Is64Bit) { return(false); } if (candidate.Implementation.Architecture.Cpu.Is64Bit() && Selections.Is32Bit) { return(false); } if (restriction.Versions != null && !restriction.Versions.Match(candidate.Version)) { return(false); } if (nativeImplementation != null && !restriction.Distributions.ContainsOrEmpty(nativeImplementation.Distribution)) { return(false); } } // Ensure the existing selections do not conflict with restrictions of the candidate foreach (var restriction in candidate.Implementation.GetEffectiveRestrictions()) { var selection = Selections.GetImplementation(restriction.InterfaceUri); if (selection != null) { if (restriction.Versions != null && !restriction.Versions.Match(selection.Version)) { return(false); } if (nativeImplementation != null && !restriction.Distributions.ContainsOrEmpty(nativeImplementation.Distribution)) { return(false); } } } return(true); });
protected override bool TryFulfill(SolverDemand demand, IEnumerable <SelectionCandidate> candidates) { foreach (var selection in candidates.ToSelections(demand)) { Selections.Implementations.Add(selection); if (TryFulfill(DemandsFor(selection, demand.Requirements))) { return(true); } else { Selections.Implementations.RemoveLast(); } } if (_backtrackCounter++ >= MaxBacktrackingSteps) { throw new SolverException("Too much backtracking; dependency graph too complex."); } return(false); }
/// <summary> /// Tries to fulfill the specified solver demand. Adds the result to <see cref="Selections"/> if successful. /// </summary> /// <param name="demand">The demand to fulfill.</param> /// <param name="candidates">The candidates to consider for fulfilling the demand.</param> /// <returns><c>true</c> if the demand could be met, <c>false</c> if not.</returns> protected abstract bool TryFulfill(SolverDemand demand, IEnumerable <SelectionCandidate> candidates);
public static IEnumerable <ImplementationSelection> ToSelections(this IEnumerable <SelectionCandidate> candidates, SolverDemand demand) => candidates.Select(x => x.ToSelection(demand.Requirements, allCandidates: demand.Candidates));
/// <summary> /// Gets all <see cref="SelectionCandidate"/>s for the <paramref name="demand"/> that are compatible with the current <see cref="Selections"/> state. /// </summary> private IEnumerable <SelectionCandidate> GetCompatibleCandidates(SolverDemand demand) => demand.Candidates.Where(candidate =>