Using Reflection with a collection class - syntax question

G

Guest

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!
 
N

Nicholas Paldino [.NET/C# MVP]

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.
 
A

Alun Harford

Econnolly said:
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.

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

Alun Harford
 
M

Marc Gravell

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);

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
 
G

Guest

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!
 
J

Jon Skeet [C# MVP]

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.).

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
 
G

Guest

OK, I will put together a simple program to demonstrate this (or perhaps
figure out what I'm doing wrong) shortly. Thanks.
 
G

Guest

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;
}

}
}
}
 
M

Marc Gravell

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; // need to
cast since IList returns object
string s = "Animal " + i.ToString() + " is named " +
animal.MyName + " and has fur colored " +
animal.FurColor;
Console.WriteLine(s);
}

Marc
 
M

Marc Gravell

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
 
A

André Matos

I wanted to do something a little bit different (kind of a property editor capable of adding new items to collections), and your post about IList helped me a lot, so thank you very much!



Marc Gravell wrote:

Can I just take this back a level... "why?
21-Oct-07

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

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

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

Marc

Previous Posts In This Thread:

Using Reflection with a collection class - syntax question
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 lik

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




--
E. Connolly

Econnolly, What you want to do is get the PropertyInfo for the item
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

--
- Nicholas Paldino [.NET/C# MVP
- (e-mail address removed)


Re: Using Reflection with a collection class - syntax question
Econnolly wrote

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

Alun Harford

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

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

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

Marc

Thank you all of you for these suggestions.
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!

--
E. Connolly


:

Re: Using Reflection with a collection class - syntax question
On Oct 22, 3:04 pm, Econnolly <[email protected]>
wrote:

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

OK, I will put together a simple program to demonstrate this (or perhaps
OK, I will put together a simple program to demonstrate this (or perhaps
figure out what I am doing wrong) shortly. Thanks.
--
E. Connolly


:

As suggested, I created a a short, silly, but complete program illustrating
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;
}

}
}
}



--
E. Connolly


:

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

Marc

Re: Using Reflection with a collection class - syntax question
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

Hmm.... this may be just exactly what I need! I will try this. Thanks!!!
Hmm.... this may be just exactly what I need! I will try this. Thanks!!!
--
E. Connolly


:


Submitted via EggHeadCafe - Software Developer Portal of Choice
Visual Studio 2005: Cool Debugging Tricks
http://www.eggheadcafe.com/tutorial...2ed-92fb0ad72bec/visual-studio-2005-cool.aspx
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top