I have a bunch of IEnumerable Collections which exact number and types is subject of frequent changes (due to automatic code generation).
It looks something like this:
public class MyCollections {
public System.Collections.Generic.IEnumerable<SomeType> SomeTypeCollection;
public System.Collections.Generic.IEnumerable<OtherType> OtherTypeCollection;
...
At runtime i want to determine each Type and it's count without having to rewrite the code after every code generation. So i am looking for a generic approach using reflection. The result i am looking for is something like:
MyType: 23
OtherType: 42
My problem is that i can't figure how to invoke the Count method properly. Here is what i have so far:
// Handle to the Count method of System.Linq.Enumerable
MethodInfo countMethodInfo = typeof(System.Linq.Enumerable).GetMethod("Count", new Type[] { typeof(IEnumerable<>) });
PropertyInfo[] properties = typeof(MyCollections).GetProperties();
foreach (PropertyInfo property in properties)
{
Type propertyType = property.PropertyType;
if (propertyType.IsGenericType)
{
Type genericType = propertyType.GetGenericTypeDefinition();
if (genericType == typeof(IEnumerable<>))
{
// access the collection property
object collection = property.GetValue(someInstanceOfMyCollections, null);
// access the type of the generic collection
Type genericArgument = propertyType.GetGenericArguments()[0];
// make a generic method call for System.Linq.Enumerable.Count<> for the type of this collection
MethodInfo localCountMethodInfo = countMethodInfo.MakeGenericMethod(genericArgument);
// invoke Count method (this fails)
object count = localCountMethodInfo.Invoke(collection, null);
System.Diagnostics.Debug.WriteLine("{0}: {1}", genericArgument.Name, count);
}
}
}
Simplifying all answer. IEnumerable has not Count function or property. To get this, you can store count variable (with foreach, for example) or solve using Linq to get count. Save this answer.
To count the number of elements in the C# array, we can use the count() method from the IEnumerable. It is included in the System.
The most basic enumerable is an array, which can store a fixed number of typed elements. int[] numbers = new int[3] { 1, 2, 3}; In the example above, we create an integer array that can hold 3 values and initialize the array with the values 1, 2 and 3.
If you need to read the number of items in an IEnumerable<T> you have to call the extension method Count , which in general (look at Matthew comment) would internally iterate through the elements of the sequence and it will return you the number of items in the sequence. There isn't any other more immediate way.
If you insist on doing it the hard way ;p
Changes:
Code (note obj
is my instance of MyCollections
):
MethodInfo countMethodInfo = typeof (System.Linq.Enumerable).GetMethods().Single(
method => method.Name == "Count" && method.IsStatic && method.GetParameters().Length == 1);
PropertyInfo[] properties = typeof(MyCollections).GetProperties();
foreach (PropertyInfo property in properties)
{
Type propertyType = property.PropertyType;
if (propertyType.IsGenericType)
{
Type genericType = propertyType.GetGenericTypeDefinition();
if (genericType == typeof(IEnumerable<>))
{
// access the collection property
object collection = property.GetValue(obj, null);
// access the type of the generic collection
Type genericArgument = propertyType.GetGenericArguments()[0];
// make a generic method call for System.Linq.Enumerable.Count<> for the type of this collection
MethodInfo localCountMethodInfo = countMethodInfo.MakeGenericMethod(genericArgument);
// invoke Count method (this fails)
object count = localCountMethodInfo.Invoke(null, new object[] {collection});
System.Diagnostics.Debug.WriteLine("{0}: {1}", genericArgument.Name, count);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With