Как я могу получить счет от ICollection <T>с неизвестным T - PullRequest
4 голосов
/ 29 ноября 2011

Вот мой код:

//TODO: Look for a way of handling ICollection<T>

if (value is ICollection)
{
    return CreateResult(validationContext, ((ICollection)value).Count);
}

if (value is IEnumerable)
{
    var enumerator = ((IEnumerable)value).GetEnumerator();
    try
    {
        var count = 0;
        while (enumerator.MoveNext())
            count++;
        return CreateResult(validationContext, count);
    }
    finally
    {
        if (enumerator is IDisposable)
            ((IDisposable)enumerator).Dispose();
    }

}

Есть ли хороший способ получить Count из ICollection<T>, не прибегая к переборам в коллекции?

Ответы [ 4 ]

5 голосов
/ 29 ноября 2011

Не имея закрытого типа ICollection<T>, вам придется прибегнуть к рефлексии, чтобы вызвать свойство Count.

if (typeof(ICollection<>) == value.GenericTypeDefinition()) {
  var countProp = value.GetType().GetProperty("Count");
  var count = (int)countProp.GetValue(value, null);
}
4 голосов
/ 29 ноября 2011

Вы должны будете использовать отражение:

var genCollType = value.GetType()
                       .GetInterfaces()
                       .FirstOrDefault
                           (i => i.IsGenericType 
                              && i.GetGenericTypeDefinition() == typeof(ICollection<>));

if (genCollType != null)
{
    int count = (int)genCollType.GetProperty("Count")
                                .GetValue(value, null);

    return CreateResult(validationContext, count);   
}
1 голос
/ 29 ноября 2011

Отражение было бы хорошим способом, но имейте в виду, что большинство коллекций в FCL наследуются как от ICollection<T>, так и от ICollection. Так что код, подобный этому, работает:

var collection = new List<int>();
Console.WriteLine(collection is ICollection<MyClass>);
Console.WriteLine(collection is ICollection);

True isвыход для обоих.Это работает для большинства, если не для всех коллекций в FCL.Если вам нужно было работать с пользовательскими коллекциями или коллекциями, которые не реализуют ICollection, то отражение - единственный способ.

Sidenote: массивы также неявно реализуют ICollection, IList и IEnumerable (CLR фактически генерирует массивкоторый наследует от универсальных версий этих классов в дополнение к неуниверсальным во время выполнения), поэтому приведенный выше код будет работать и с массивами.

0 голосов
/ 29 ноября 2011

Интерфейсы ICollection и IEnumerable имеют свойство Count. Общие версии также.

if (value is ICollection)
{
    return CreateResult(validationContext, ((ICollection)value).Count);
}

if (value is IEnumerable)
{
     return CreateResult(validationContext, ((IEnumerable)value).Count);
}

Документация MSDN для ICollection http://msdn.microsoft.com/en-us/library/system.collections.icollection.aspx

Документация MSDN для IEnumerable http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...