/// <summary> /// Examines a <see cref="ConstructorInfo"/> instance /// and determines if it can be instantiated with the services embedded in /// the target <paramref name="container"/>. /// </summary> /// <param name="fuzzyItem">The <see cref="FuzzyItem{T}"/> that represents the constructor to be examined.</param> /// <param name="container">The container that contains the services that will be used to instantiate the target type.</param> /// <param name="maxIndex">Indicates the index that /// marks the point where the user-supplied arguments begin.</param> private static void CheckParameters(IFuzzyItem <TMethod> fuzzyItem, IServiceContainer container, int maxIndex) { var constructor = fuzzyItem.Item; var currentIndex = 0; foreach (var param in constructor.GetParameters()) { if (currentIndex == maxIndex) { break; } var parameterType = param.ParameterType; var criteria = new Criteria <TMethod> { Type = CriteriaType.Critical, Weight = 1 }; // The type must either be an existing service // or a list of services that can be created from the container var predicate = parameterType.MustExistInContainer() .Or(parameterType.ExistsAsServiceArray()) .Or(parameterType.ExistsAsEnumerableSetOfServices()); criteria.Predicate = currentConstructor => predicate(container); fuzzyItem.Test(criteria); currentIndex++; } }
private T GetNextBestMatch(IList <IFuzzyItem <T> > fuzzyList, List <Type> additionalArgumentTypes, T bestMatch) { int additionalArgumentCount = additionalArgumentTypes.Count; fuzzyList.Reset(); // Match the number of arguments Func <T, bool> matchParameterCount = method => { ParameterInfo[] parameters = method.GetParameters(); int parameterCount = parameters != null ? parameters.Length : 0; return(parameterCount == additionalArgumentCount); }; // Remove any methods that do not match // the parameter count fuzzyList.AddCriteria(matchParameterCount, CriteriaType.Critical); CheckArguments(fuzzyList, additionalArgumentTypes); IFuzzyItem <T> nextBestMatch = fuzzyList.BestMatch(); if (nextBestMatch == null) { return(null); } return(nextBestMatch.Item); }
public void ShouldReturnNullIfAllMatchScoresAreZero() { var fuzzyItem = new FuzzyItem <object>(new object()); var fuzzyList = new List <IFuzzyItem <object> > { fuzzyItem }; IFuzzyItem <object> bestMatch = fuzzyList.BestMatch(); Assert.IsNull(bestMatch); }
public void ShouldNotBeAbleToIgnoreFailedCriticalCriteria() { var fuzzyList = new List <IFuzzyItem <object> >(); var fuzzyItem = new FuzzyItem <object>(new object()); fuzzyList.Add(fuzzyItem); Mock <ICriteria <object> > trueCriteria = GetMockCriteria(true, CriteriaType.Standard, 2); Mock <ICriteria <object> > failedCriteria = GetMockCriteria(false, CriteriaType.Critical, 1); // Boost the first item results so that the best match // should be biased towards the first item fuzzyItem.Test(trueCriteria.Object); // Make both items pass the first test var secondItem = new FuzzyItem <object>(new object()); fuzzyList.Add(secondItem); fuzzyList.AddCriteria(trueCriteria.Object); // The first item should be the best match at this point IFuzzyItem <object> bestMatch = fuzzyList.BestMatch(); Assert.AreSame(bestMatch, fuzzyItem); // Remove the second item from the list to avoid the // failed critical match fuzzyList.Remove(secondItem); // The failed critical criteria should eliminate // the first match as the best possible match fuzzyList.AddCriteria(failedCriteria.Object); // Reinsert the second value into the list // so that it can be chosen as the best match fuzzyList.Add(secondItem); // Run the test again bestMatch = fuzzyList.BestMatch(); // The second item should be the best possible match, // and the first item should be ignored // because of the failed criteria Assert.AreSame(bestMatch, secondItem); }
/// <summary> /// Returns the FuzzyItem with the highest confidence score in a given /// <see cref="IFuzzyItem{T}"/> list. /// </summary> /// <typeparam name="TItem">The type of item being compared.</typeparam> /// <param name="list">The fuzzy list that contains the list of possible matches.</param> /// <returns>The item with the highest match.</returns> public static IFuzzyItem <TItem> BestMatch <TItem>(this IList <IFuzzyItem <TItem> > list) { double bestScore = 0; IFuzzyItem <TItem> bestMatch = null; foreach (var item in list) { if (item.Confidence <= bestScore) { continue; } bestMatch = item; bestScore = item.Confidence; } return(bestMatch); }
public void ShouldBeAbleToDetermineBestFuzzyMatch() { var mockFuzzyItem = new Mock <IFuzzyItem <object> >(); IFuzzyItem <object> fuzzyItem = mockFuzzyItem.Object; // This should be the best match mockFuzzyItem.Expect(f => f.Confidence).Returns(.8); var otherMockFuzzyItem = new Mock <IFuzzyItem <object> >(); IFuzzyItem <object> fauxFuzzyItem = otherMockFuzzyItem.Object; // This fuzzy item should be ignored since it has // a lower confidence rate otherMockFuzzyItem.Expect(f => f.Confidence).Returns(.1); var fuzzyList = new List <IFuzzyItem <object> > { fuzzyItem, fauxFuzzyItem }; IFuzzyItem <object> bestMatch = fuzzyList.BestMatch(); Assert.AreSame(bestMatch, fuzzyItem); }
public void ShouldBeAbleToAddCriteriaToList() { // Return a predicate that always returns true var mockCriteria = new Mock <ICriteria <object> >(); ICriteria <object> criteria = mockCriteria.Object; var mockFuzzyItem = new Mock <IFuzzyItem <object> >(); IFuzzyItem <object> fuzzyItem = mockFuzzyItem.Object; // The Test method must be called on the fuzzy item mockFuzzyItem.Expect(fuzzy => fuzzy.Test(criteria)); // Initialize the list of fuzzy items var fuzzyList = new List <IFuzzyItem <object> >(); fuzzyList.Add(fuzzyItem); // Apply the criteria fuzzyList.AddCriteria(criteria); mockCriteria.VerifyAll(); mockFuzzyItem.VerifyAll(); }
/// <summary> /// Returns the FuzzyItem with the highest confidence score in a given /// <see cref="IFuzzyItem{T}"/> list. /// </summary> /// <typeparam name="TItem">The type of item being compared.</typeparam> /// <param name="list">The fuzzy list that contains the list of possible matches.</param> /// <param name="tolerance">The tolerance level that determines the minimum percentage for a valid match (ranges between 0.0 and 1.0)</param> /// <returns>The item with the highest match.</returns> public static IFuzzyItem <TItem> BestMatch <TItem>(this IEnumerable <IFuzzyItem <TItem> > list, double tolerance) { if (tolerance < 0 || tolerance > 1) { throw new ArgumentOutOfRangeException("tolerance"); } double bestScore = 0; IFuzzyItem <TItem> bestMatch = null; foreach (var item in list) { if (item.Confidence <= bestScore || item.Confidence < tolerance) { continue; } bestMatch = item; bestScore = item.Confidence; } return(bestMatch); }