J'ai construit une bibliothèque d'extensions, et j'ai utilisé une excellente méthode d'extension trouvée à http://www.extensionmethod.net pour l'inclusion. Dans mon test d'unité (en utilisant NUnit 1.5.2), j'ai rencontré un problème intéressant. Tout d'abord, permet de regarder le code:KeyNotFoundException, mais pas lors du débogage
/// <summary>
/// Groups and aggregates the sequence of elements.
/// </summary>
/// <typeparam name="TSource">The source type in the sequence.</typeparam>
/// <typeparam name="TFirstKey">The first key type to group by.</typeparam>
/// <typeparam name="TSecondKey">The second key type to rotate by.</typeparam>
/// <typeparam name="TValue">The type of value that will be aggregated.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="firstKeySelector">The first key selector.</param>
/// <param name="secondKeySelector">The second key selector.</param>
/// <param name="aggregator">The aggregating function.</param>
/// <returns>A <see cref="Dictionary{TKey,TValue}" /> representing the pivoted data.</returns>
public static Dictionary<TFirstKey, Dictionary<TSecondKey, TValue>> Pivot<TSource, TFirstKey, TSecondKey, TValue>
(this IEnumerable<TSource> source,
Func<TSource, TFirstKey> firstKeySelector,
Func<TSource, TSecondKey> secondKeySelector,
Func<IEnumerable<TSource>, TValue> aggregator)
{
return source.GroupBy(firstKeySelector).Select(
x => new
{
X = x.Key,
Y = x.GroupBy(secondKeySelector).Select(
z => new { Z = z.Key, V = aggregator(z) }).ToDictionary(e => e.Z, o => o.V)
}).ToDictionary(e => e.X, o => o.Y);
}
quoi correspond la fonction, est prend dans un IEnumerable de type TSource, et fait pivoter les éléments dans un dictionnaire et agrège les éléments à l'aide quelle que soit la fonction que vous définissez. Mon exemple de jeu de données est un tableau de personnes (dans un type appelé Personne).
private static readonly Person[] people =
new[]
{
new Person { Forename = "Matt", Surname = "Someone", Email = "[email protected]", Age = 25, IsMale = true },
new Person { Forename = "Chris", Surname = "Someone", Email = "[email protected]", Age = 28, IsMale = false },
new Person { Forename = "Andy", Surname = "Someone", Email = "[email protected]", Age = 30, IsMale = true },
new Person { Forename = "Joel", Surname = "Someone", Email = "[email protected]", Age = 30, IsMale = true },
new Person { Forename = "Paul", Surname = "Someone", Email = "[email protected]", Age = 30, IsMale = true }
};
Et enfin, nous faisons notre test:
/// <summary>
/// Performs a pivot function on the sample array.
/// </summary>
[Test]
public void Pivot()
{
/* Our sample data is an array of Person instances.
* Let's organise it first by gender (IsMale), and then by Age.
* Finally, we'll return a count. */
var organised = people.Pivot(p => p.IsMale, p => p.Age, l => l.Count());
Assert.IsTrue(organised.Count == 2, "More than two genders were returned.");
Assert.IsTrue(organised[true].Count == 2, "More than two ages were returned for males.");
Assert.IsTrue(organised[false].Count == 1, "More than 1 age was returned for females.");
int count = organised[true][30];
Assert.IsTrue(count == 3, "There are more than 3 male 30 year olds in our data.");
}
Ce qui est renvoyé dans ce cas de test, est un dictionnaire> exemple. Le booléen est un résultat du groupe IsMale par, et dans nos exemples de données, renvoie correctement 2 éléments, vrai et faux. Le dictionnaire interne a une clé de l'âge, et une valeur du compte. Dans nos données de test, organisé [true] [30] reflète tous les mâles de l'âge de 30 ans dans l'ensemble. Le problème n'est pas la fonction pivot elle-même, mais pour une raison quelconque, lorsque nous l'exécutons à la fois avec NUnit Test Runner et Unit Runner Runner de Resharper, le test échoue, signalant une exception KeyNotFoundException pour la ligne "int count = organisée [vrai] [30]; " Lorsque nous déboguons ce test, il renvoie correctement la valeur 3 (comme dans notre exemple de données, nous avons 3 mâles de 30 ans).
Des pensées?
J'ai exécuté NUnit en externe, mais j'ai utilisé le testeur d'unité de Resharper en interne de VS. Les deux échouent sans déboguer, mais marcher fonctionne bien. –