Jako projekt hobbistyczny (i głębiej zanurzam się w metodach generycznych/rozszerzających) piszę bibliotekę do sprawdzania parametrów!W jaki sposób można dołączyć metodę rozszerzenia do klasy ogólnej, gdy argumentem typu jest IEnumerable <T>?
mam model o nazwie argument, że opisuje parametr i wygląda tak:
public class Argument<T>
{
internal Argument(string name, T value)
{
Name = name;
Value = value;
}
public string Name { get; private set; }
public T Value { get; private set; }
}
Po walidacji parametru rozpoczyna wystąpienie tego obiektu jest tworzony, a poszczególne walidacji są wykonywane przez wywołanie metody rozszerzenie (które zawierają rzeczywistą logikę), która się z tym wiąże.
Jedną z takich metod rozszerzenie sprawdza, czy kolekcja zawiera co najmniej jeden element, a obecnie wygląda następująco:
public static Argument<IEnumerable<T>> HasItems<T>(this Argument<IEnumerable<T>> argument)
{
if (!argument.Value.Any())
throw Error.Generic(argument.Name, "Collection contains no items.");
return argument;
}
Ale to nie wydaje się działać. Gdybym był, powiedzmy, aby napisać ten test Jednostka:
[TestMethod]
public void TestMethod1()
{
var argument = new List<int>() { 1, 2, 6, 3, -1, 5, 0 };
Validate.Argument("argument", argument)
.IsNotNull()
.HasItems()
.All(v => v.IsGreaterThan(0));
}
HasItems nie pojawi się w IntelliSense, i otrzymuję ten błąd kompilacji:
'Validation.Argument<System.Collections.Generic.List<int>>'
does not contain a definition for 'HasItems' and no extension method 'HasItems' accepting a first argument of type'Validation.Argument<System.Collections.Generic.List<int>>'
could be found (are you missing a using directive or an assembly reference?)
A jeśli staram przepuszczenie wartość bezpośrednio do metody rozszerzenia, tak:
CollectionTypeExtensions.HasItems(Validate.Argument("argument", argument));
uzyskać to:
The best overloaded method match for
'Validation.CollectionTypeExtensions.HasItems<int>(Validation.Argument<System.Collections.Generic.IEnumerable<int>>)'
has some invalid arguments
podstawie moich badań, co bym potrzebne do tego, aby praca nazywana jest „odchylenie” i odnosi się do interfejsów i delegatów, ale nie do klas (tj. Wszystkie klasy są niezmienne)
Że powiedział, może działać inaczej. Jeden, który przychodzi do głowy to przepisać go prosto do T, tak jak poniżej:
public static Argument<T> HasItems<T, TElement>(this Argument<T> argument)
where T : IEnumerable<TElement>
{
if (!argument.Value.Any())
throw Error.Generic(argument.Name, "Collection contains no items.");
return argument;
}
..ale że nie działa albo ponieważ wymaga TElement być określony jawnie, gdy metoda jest wywoływana. Mógłbym też cofnąć się do używania nietypowego interfejsu IEnumerable w ograniczeniu typu, ale wtedy musiałbym albo znaleźć sposób na wymuszenie IEnumerable na IEnumerable (co wymagałoby poznania, co T jest w tym kontekście), albo powielenie funkcjonalność Any() w celu przetestowania istnienia jakichkolwiek elementów, i jest inna metoda rozszerzenia (All), która byłaby bardzo, bardzo niechlujna, więc wolałbym tego uniknąć.
Ostatecznie, myślę, że moje pytanie brzmi: w jaki sposób uzyskać właściwą metodę dołączania?
... To rzeczywiście działa! Kiedy spojrzałem na to świeżymi oczami dziś rano, wylądowałem na innej drodze, ale zaznaczam jako odpowiedź, ponieważ zwięźle rozwiązuje problem w przedstawiony sposób. Dzięki! –