Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / October 2007

Tip: Looking for answers? Try searching our database.

Using Reflection with a collection class - syntax question

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Econnolly - 21 Oct 2007 02:57 GMT
Hi,

I hope this is the right forum for this question.

I am trying to use reflection for several custom collection classes. For
example, what I want to do is take a line of code like this:

   myCollection.Add(mySecondCollection.Item(i))

and rewrite it using reflection.

So far, I have something like

object myObject = new object();
object mySecondObject = new object();
myObject = myCollection;
mySecondObject = mySecondCollection;

myCollection.GetType().GetMethod("Add").Invoke(....

After the invoke is where I am confused about the syntax to use to represent
the second collection, and to represent the .Item syntax (.Item is a custom
method that returns an object in the collection and takes the collection
index as an argument).

I have read the documentation for .GetMethod, .Invoke, etc. and don't
understand what I'm supposed to do in this case.

Any help would be greatly appreciated.

Thanks!

Signature

E. Connolly

Nicholas Paldino [.NET/C# MVP] - 21 Oct 2007 03:01 GMT
Econnolly,

   What you want to do is get the PropertyInfo for the item property that
is exposed.  Once you have that, you should be able to call the GetValue
method on the PropertyInfo, and use that value to pass the parameter to the
MethodInfo instance to invoke the method.

Signature

         - Nicholas Paldino [.NET/C# MVP]
         - mvp@spam.guard.caspershouse.com

> Hi,
>
[quoted text clipped - 29 lines]
>
> Thanks!
Alun Harford - 21 Oct 2007 13:04 GMT
> Hi,
>
[quoted text clipped - 6 lines]
>
> and rewrite it using reflection.

myCollection.GetType().InvokeMember("Add", BindingFlags.Public |
BindingFlags.Instance | BindingFlags.InvokeMethod, null, myCollection,
new object[] { mySecondCollection.Item(i) });

Alun Harford
Marc Gravell - 21 Oct 2007 20:18 GMT
> I am trying to use reflection for several custom collection classes

Can I just take this back a level... "why?"
The standard way of working with collections (without needing to know
much about them) would be to simply cast it to IList. This requires
very little knowledge of the contents, and is supported by almost
every container - i.e.

       int i;
       IList col1, col2;
       // init vars...
       col1.Add(col2[i]);

This will out-perform reflection *every* time. If you wanted to get
more type-safe, this also offers the option to move to generics,
simply by moving to IList<T>...

Marc
Econnolly - 22 Oct 2007 15:04 GMT
Thank you all of you for these suggestions.

The idea of NOT using reflection for this is a great one; reflection does
seem like overkill to me. However, because of the way these custom collection
classes are set up (and I can't want to change them right now) they are
derived from System.Collections.Base, each take specific objects in the .Add,
etc. methods, and I can't seem to use System.Collections.IList (can't cast
these objects to it.). Can you point me to any favorite samples that do this?
I've also tried the same thing with System.Collections.ArrayList - can't cast
to that either.

In using reflection, the .Item is actually a method, and not a property - so
the propertyinfo idea doesn't seem to work. But I have been able to get
something like this working to get the correct instance of the item I want in
my first collection. Stepping through, "arg" below is exactly the right
object. But when I try to add this object to the second collection, it
doesn't work - I get an "Object does not match target type." error when I go
to execute the last line of code. I know arg is the object I want to add.

                   object[] propindexes = new object[] { b };
                   object arg =
_mycollection.GetType().GetMethod("Item").Invoke(_mycollection, propindexes);
                   object[] argparms = new object[] { 0 };
                   
_mysecondcollection.GetType().GetMethod("Add").Invoke(arg, argparms);

Any idea which object does not match which target type???

Thanks for your help!

Signature

E. Connolly

> Hi,
>
[quoted text clipped - 27 lines]
>
> Thanks!
Jon Skeet [C# MVP] - 22 Oct 2007 15:15 GMT
On Oct 22, 3:04 pm, Econnolly <econno...@disccussions.microsoft.com>
wrote:
> Thank you all of you for these suggestions.
>
[quoted text clipped - 4 lines]
> etc. methods, and I can't seem to use System.Collections.IList (can't cast
> these objects to it.).

That sounds very odd to me. CollectionBase implements IList, so you
should be able to cast without any issues. You wouldn't be able to
cast to ArrayList, because it's not an ArrayList - but IList should
work fine.

Can you post a short but complete program which demonstrates deriving
from CollectionBase but not being able to cast to IList?

Jon
Econnolly - 22 Oct 2007 15:31 GMT
OK, I will put together a simple program to demonstrate this (or perhaps
figure out what I'm doing wrong) shortly. Thanks.
Signature

E. Connolly

> On Oct 22, 3:04 pm, Econnolly <econno...@disccussions.microsoft.com>
> wrote:
[quoted text clipped - 16 lines]
>
> Jon
Econnolly - 23 Oct 2007 02:06 GMT
As suggested, I created a a short, silly, but complete program illustrating
the collection classes that I'm using. Can you show me how I'd cast an
instance of the AnimalCollection to System.Collections.IList? (NOT the
generic IList<T>!) Greatly appreciate the help!

using System;
using System.Collections.Generic;
using System.Text;

namespace IlistTest
   {
   class Program
       {
       static void Main(string[] args)
           {
           AnimalCollection beasts = new AnimalCollection();
           beasts.LoadCollection();
           for (int i = 0; i < beasts.Count; i++)
               {
               string s = "Animal " + i.ToString() + " is named " +
beasts.Item(i).MyName + " and has fur colored " + beasts.Item(i).FurColor;
               Console.WriteLine(s);
               }
           }

       public class Animal
           {
           private string _MyName;
           private string _FurColor;

           public string MyName
               {
               get { return _MyName; }
               set { _MyName = value; }
               }
           public string FurColor
               {
               get { return _FurColor; }
               set { _FurColor = value; }
               }
           }

       public class AnimalCollection : System.Collections.CollectionBase
           {

           public void Add(Animal obj)
               {
               List.Add(obj);
               }
           public void Remove(int index)
               {

               if (index < Count - 1 && index > 0)
                   {
                   List.RemoveAt(index);
                   }
               }
           public Animal Item(int index)
               {
               return (Animal)List[index];
               }
           public bool LoadCollection()
               {

               Animal oAnimal = new Animal();
               this.Add(oAnimal);

               //just an example - in real life would be loaded from a data
source
               oAnimal.FurColor = "Red";
               oAnimal.MyName = "Mr. Fox";
               Console.WriteLine ("The first animal loaded in the
collection is {0}",oAnimal.MyName);

               oAnimal = new Animal();
               this.Add(oAnimal);

               oAnimal.FurColor = "Brindle";
               oAnimal.MyName = "Mrs. Greyhound";
               Console.WriteLine("The first animal loaded in the collection
is {0}", oAnimal.MyName);

               return true;
               }

           }
       }
   }

Signature

E. Connolly

> On Oct 22, 3:04 pm, Econnolly <econno...@disccussions.microsoft.com>
> wrote:
[quoted text clipped - 16 lines]
>
> Jon
Marc Gravell - 23 Oct 2007 05:07 GMT
> Can you show me how I'd cast an instance of the
> AnimalCollection to System.Collections.IList? (NOT
> the generic IList<T>!) Greatly appreciate the help!

using System.Collections;
...
           IList simpleList = beasts;
           for (int i = 0; i < simpleList.Count; i++) {
               Animal animal = (Animal) simpleList[i]; // need to
cast since IList[i] returns object
               string s = "Animal " + i.ToString() + " is named " +
                   animal.MyName + " and has fur colored " +
animal.FurColor;
               Console.WriteLine(s);
           }

Marc
Marc Gravell - 23 Oct 2007 05:14 GMT
Additional few points:
           public Animal Item(int index)
               {
               return (Animal)List[index];
               }

This looks and feels like an indexer; you can enable indexer usage via
(instead):

 public Animal this[int index] {
   get { return (Animal) List[index];}
 }

However, an even simpler option (in 2.0) is to subclass either List<T>
or Collection<T> - example below. This retains IList support, but adds
IList<T> support, and you don't need to add your own typed Add etc
methods:

       public class AnimalCollection : Collection<Animal> {
           public bool LoadCollection() {
             // ... LoadCollection unchanged
           }
       }

Marc
Econnolly - 23 Oct 2007 13:19 GMT
Hmm.... this may be just exactly what I need! I will try this. Thanks!!!
Signature

E. Connolly

> Additional few points:
>             public Animal Item(int index)
[quoted text clipped - 21 lines]
>
> Marc

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.