13

This (shortened) code..

for (int i = 0; i < count; i++)
{
    object obj = propertyInfo.GetValue(Tcurrent, new object[] { i });
}

.. is throwing a 'TargetParameterCountException : Parameter count mismatch' exception.

The underlying type of 'propertyInfo' is a Collection of some T. 'count' is the number of items in the collection. I need to iterate through the collection and perform an operation on obj.

Advice appreciated.

flesh
  • 23,725
  • 24
  • 80
  • 97

3 Answers3

20

Reflection only works on one level at a time.

You're trying to index into the property, that's wrong.

Instead, read the value of the property, and the object you get back, that's the object you need to index into.

Here's an example:

using System;
using System.Collections.Generic;
using System.Reflection;

namespace DemoApp
{
    public class TestClass
    {
        public List<Int32> Values { get; private set; }

        public TestClass()
        {
            Values = new List<Int32>();
            Values.Add(10);
        }
    }

    class Program
    {
        static void Main()
        {
            TestClass tc = new TestClass();

            PropertyInfo pi1 = tc.GetType().GetProperty("Values");
            Object collection = pi1.GetValue(tc, null);

            // note that there's no checking here that the object really
            // is a collection and thus really has the attribute
            String indexerName = ((DefaultMemberAttribute)collection.GetType()
                .GetCustomAttributes(typeof(DefaultMemberAttribute),
                 true)[0]).MemberName;
            PropertyInfo pi2 = collection.GetType().GetProperty(indexerName);
            Object value = pi2.GetValue(collection, new Object[] { 0 });

            Console.Out.WriteLine("tc.Values[0]: " + value);
            Console.In.ReadLine();
        }
    }
}
Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • 2
    ok, i understand, thanks for the response. it's now working but would be interested to know about the "Item" property if anyone does know... – flesh Jun 01 '09 at 23:25
  • Found it, changed the answer. The attribute was on the class, not on the property. Note that classes that doesn't have an indexer doesn't have the attribute either. – Lasse V. Karlsen Jun 01 '09 at 23:55
  • noted - i do the collection check further up in my code. thanks for the update :) – flesh Jun 02 '09 at 10:53
  • During debugging I see that `indexerName` contains the value "Item". Is it always this name? If yes, we could remove the mystical lines for getting the indexer name and just write `PropertyInfo pi2 = collection.GetType().GetProperty("Item");`. Can we do that or is it a pitfall? – Beauty Jun 27 '22 at 20:40
  • @Beauty C# does not allow you to (re)name the default indexer. Other languages, like VB.NET, does. – Lasse V. Karlsen Jun 30 '22 at 09:28
  • Thanks for your answer. So it's possible to use my suggested code to keep the solution more simple. The code `String indexerName = ...` isn't needed, because it always returns the value `Item`. – Beauty Jul 25 '22 at 09:53
  • @Beauty For C# written code, yes, it will. In the general sense, it is still needed. Besides, you can cache most of that code anyway, reflection objects doesn't change over time, so once you've obtained them you can cache them for the process' lifetime. – Lasse V. Karlsen Jul 25 '22 at 18:48
2

I was most of the way there until I saw this, and I am posting this because I didn't see it anywhere else; the key was using GetValue(collection, new Object[] { i }); in the loop rather than trying to use GetValue(collection, new Object[i]); outside the loop. (You can probably ignore the "output" in my example);

private static string Recursive(object o)
{ 
        string output="";
        Type t = o.GetType();
        if (t.GetProperty("Item") != null)
        {
            System.Reflection.PropertyInfo p = t.GetProperty("Item");
            int count = -1;
            if (t.GetProperty("Count") != null && 
                t.GetProperty("Count").PropertyType == typeof(System.Int32))
            {
                count = (int)t.GetProperty("Count").GetValue(o, null);
            }
            if (count > 0)
            {
                object[] index = new object[count];
                for (int i = 0; i < count; i++)
                {
                    object val = p.GetValue(o, new object[] { i });
                    output += RecursiveWorker(val, p, t);
                }
            }
       }
       return output;        
}
maxp
  • 24,209
  • 39
  • 123
  • 201
0
Assembly zip_assembly = Assembly.LoadFrom(@"C:\Ionic.Zip.Reduced.dll");
Type ZipFileType = zip_assembly.GetType("Ionic.Zip.ZipFile");
Type ZipEntryType = zip_assembly.GetType("Ionic.Zip.ZipEntry");
string local_zip_file = @"C:\zipfile.zip";
object zip_file = ZipFileType.GetMethod("Read", new Type[] { typeof(string) }).Invoke(null, new object[] { local_zip_file });

// Entries is ICollection<ZipEntry>
IEnumerable entries = (IEnumerable)ZipFileType.GetProperty("Entries").GetValue(zip_file, null);
foreach (object entry in entries)
{
    string file_name = (string)ZipEntryType.GetProperty("FileName").GetValue(entry, null);
    Console.WriteLine(file_name);
}
Adi Lester
  • 24,731
  • 12
  • 95
  • 110
zioolek
  • 1
  • 1