Problem in method ElementAt using reflection

M

Milan

Hi comunity,

I have noticed that once IList object is created with:
IList<baza> il_baza = new List<baza>();

Later if I try with reflection to InvokeMember:
type.InvokeMember("ElementAt", BindingFlags.Default |
BindingFlags.InvokeMethod, null, il_baza, arg);

I get MissingMethodException error message because of type of il_baza is not
any more IList`1 but List`1:

Method "System.Collections.Generic.List`1[[Reflection.baza,
ConsoleApplication2, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null]].ElementAt" can not be found.

There are 2 questions:
1. Why type has been not read out correctly like generic IList but generic
List ?
2. How I can using reflection and il_baza call the method ElementAt ?

Thanks and have a nice day,
Milan.



The code is following:

class baza
{
public string vrati()
{ return "u bazi"; }
}

class Class1
{
[STAThread]
static void Main(string[] args)
{
IList<baza> il_baza = new List<baza>();

il_baza.Add(new baza());
il_baza.Add(new baza());
il_baza.Add(new baza());

//foliwing code works fine...it finds function "ElementAt"
il_baza.ElementAt(0);
il_baza.ElementAt(1);
il_baza.ElementAt(2);


Type type = (Type)il_baza.GetType();//returns type "List`1", why ?

object[] arg = new object[1];
arg[0] = 0;

//folowing code fires error message! it does not find "ElementAt"
type.InvokeMember("ElementAt", BindingFlags.Default |
BindingFlags.InvokeMethod, null, il_baza, arg);

}
}
 
H

Hans Kesting

Milan brought next idea :
Hi comunity,

I have noticed that once IList object is created with:
IList<baza> il_baza = new List<baza>();

Later if I try with reflection to InvokeMember:
type.InvokeMember("ElementAt", BindingFlags.Default |
BindingFlags.InvokeMethod, null, il_baza, arg);

I get MissingMethodException error message because of type of il_baza is not
any more IList`1 but List`1:

Method "System.Collections.Generic.List`1[[Reflection.baza,
ConsoleApplication2, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null]].ElementAt" can not be found.

There are 2 questions:
1. Why type has been not read out correctly like generic IList but generic
List ?
2. How I can using reflection and il_baza call the method ElementAt ?

Thanks and have a nice day,
Milan.

1) I guess because reflection uses the *real* type of the object,
instead of the declared type of the variable

2) because ElementAt is not a member method of List<T> or IList<T>,
it's an extension method, defined in System.Linq.Enumerable.

Hans Kesting
 
M

Milan

Hans said:it's an extension method, defined in System.Linq.Enumerable.

"ElementAt" is member of IList<T> and List<T> and that is why following code
works:
//foliwing code works fine...it finds function "ElementAt"
il_baza.ElementAt(0);
il_baza.ElementAt(1);
il_baza.ElementAt(2);


BR,
Milan.




Hans Kesting said:
Milan brought next idea :
Hi comunity,

I have noticed that once IList object is created with:
IList<baza> il_baza = new List<baza>();

Later if I try with reflection to InvokeMember:
type.InvokeMember("ElementAt", BindingFlags.Default |
BindingFlags.InvokeMethod, null, il_baza, arg);

I get MissingMethodException error message because of type of il_baza is not
any more IList`1 but List`1:

Method "System.Collections.Generic.List`1[[Reflection.baza,
ConsoleApplication2, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null]].ElementAt" can not be found.

There are 2 questions:
1. Why type has been not read out correctly like generic IList but generic
List ?
2. How I can using reflection and il_baza call the method ElementAt ?

Thanks and have a nice day,
Milan.

1) I guess because reflection uses the *real* type of the object,
instead of the declared type of the variable

2) because ElementAt is not a member method of List<T> or IList<T>,
it's an extension method, defined in System.Linq.Enumerable.

Hans Kesting
 
H

Hans Kesting

Milan brought next idea :
Hans said:
it's an extension method, defined in System.Linq.Enumerable.

"ElementAt" is member of IList<T> and List<T> and that is why following code
works:
//foliwing code works fine...it finds function "ElementAt"
il_baza.ElementAt(0);
il_baza.ElementAt(1);
il_baza.ElementAt(2);


BR,
Milan.
The compiler does find that method, as an extension method:
http://msdn.microsoft.com/en-us/library/bb299233.aspx

It does not exist for List<T>:
http://msdn.microsoft.com/en-us/library/d9hw1as6.aspx

What is an "extension method":
http://msdn.microsoft.com/en-us/library/bb383977.aspx

Hans Kesting
 
M

Milan

Hi Hans,

what is difference between extension methods and normal methods ?

BR,
Milan.
 
M

Milan

Hi hans,
previous question put more clear:
can I call extension methods with reflection ? and how ?


Best regards,
Milan.
 
P

Peter Duniho

Hi hans,
previous question put more clear:
can I call extension methods with reflection ? and how ?

Sure. You just have to use the correct type. In this case, the
System.Linq.Enumerable type, where the ElementAt() method exists.

There is, of course, the unanswered question, which is: do you really need
to use the ElementAt() method? List<T> and IList<T> both do provide
indexed access to the collections via the Item property, which you can
also invoke via reflection (assuming you really do need reflection at
all...there's nothing in your original question that explains or justifies
the use of reflection).

Pete
 
M

Milan

Hallo Peter,

thanks for help, sorry for my short explanation... I would need to use
reflection because from DB/NHibernate I am getting classes with different
type and different methods names so we decided to use reflection. Why
ElementAt...also once decided so no further reasons:)

With your suggestion I have a problem that "Item" is not Memeber of List<T>
or IList<T>...intel sence gives me no Item property/method. What I am doing
wrong ?

IList<baza> il_baza = new List<baza>();

il_baza.Add(new baza());
il_baza.Add(new baza());
il_baza.Add(new baza());

object[] arg = new object[1];
//object[] arg = new object[0]; I tried this also
arg[0] = 0;

il_baza.GetType().InvokeMember("Item", BindingFlags.Default |
BindingFlags.InvokeMethod, null, il_baza, arg);

Method "System.Collections.Generic.List`1[[Reflection.baza,
ConsoleApplication2, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null]].Item" can not be found.


Also I have object of type "IList" so how I can make it be type
"System.Linq.Enumerable" in order to use "ElementAt" method ?


Best regards,
Milan.
 
P

Peter Duniho

Hallo Peter,

thanks for help, sorry for my short explanation... I would need to use
reflection because from DB/NHibernate I am getting classes with different
type and different methods names so we decided to use reflection. Why
ElementAt...also once decided so no further reasons:)

With your suggestion I have a problem that "Item" is not Memeber of
List<T>
or IList<T>...intel sence gives me no Item property/method. What I am
doing
wrong ?

Off the top of my head, I couldn't say what name the "Item" property
actually has as far as reflection is concerned. It's a special property,
as it's the indexed property for the type. It's probably not literally
actually called "Item"; that's just how the documentation describes it.

I'm sure if you do some poking around, by enumerating all the methods and
properties in the type, you can figure out which of those members
corresponds to the "Item" property, and then work back from there.
[...]
Also I have object of type "IList" so how I can make it be type
"System.Linq.Enumerable" in order to use "ElementAt" method ?

You don't. You just call the Enumerable's static method with the
appropriate object.

If you don't have the original generic type parameter by the time you want
to call the ElementAt() method (from your most recent reply, it seems that
you don't), I think you'll have to use reflection to get the parameterized
type based on the type parameter of the object's IList<T> implementation,
construct a concrete generic type from that and call the
Enumerable.ElementAt() method that way.

If you are in code that knows at compile time the type of the IList<T>
object, then you can just call the method directly:

object obj = new List<Baza>();

...

IEnumerable<Baza> ebaza = (IEnumerable<Baza>)obj;

Baza baza = ebaza.ElementAt(0);

// or even more explicitly (to show the static aspect of the class):
Baza baza = Enumerable<Baza>.ElementAt(baza, 0);

Note the last line. That's all an extension method really is; it's a
special kind of static method that the compiler knows how to call even
when the code is written as if the method is an instance method on some
other type. But if you're going to be messing around with reflection, you
need to understand that it's really just a static method in the type where
the extension method is declared, not in the type where it _appears_ to be
when written as an instance method call.

Pete
 
M

Milan

Gut idea BUT there is practical problem. The first line in my project is
instead:
object obj = new List<Baza>();
it is:
object obj = new NHibernate( strClassName );

so in the line bellow I do not have hard coded "Baza" I do have only string
strClassName so on the left side since I can not dynamicly declare type just
by putting strClassName in IEnumerable<strClassName>. So I put following line
...
IEnumerable<object> ebaza = (IEnumerable<object>)obj;

but than I get exception:
Object of type \"System.Collections.Generic.List`1[System.String]\" can not
be convertet in type
\"System.Collections.Generic.IEnumerable`1[System.Object]\"

How I can List<string> cast into List<object> ?


Best regards,
Milan.








Peter Duniho said:
Hallo Peter,

thanks for help, sorry for my short explanation... I would need to use
reflection because from DB/NHibernate I am getting classes with different
type and different methods names so we decided to use reflection. Why
ElementAt...also once decided so no further reasons:)

With your suggestion I have a problem that "Item" is not Memeber of
List<T>
or IList<T>...intel sence gives me no Item property/method. What I am
doing
wrong ?

Off the top of my head, I couldn't say what name the "Item" property
actually has as far as reflection is concerned. It's a special property,
as it's the indexed property for the type. It's probably not literally
actually called "Item"; that's just how the documentation describes it.

I'm sure if you do some poking around, by enumerating all the methods and
properties in the type, you can figure out which of those members
corresponds to the "Item" property, and then work back from there.
[...]
Also I have object of type "IList" so how I can make it be type
"System.Linq.Enumerable" in order to use "ElementAt" method ?

You don't. You just call the Enumerable's static method with the
appropriate object.

If you don't have the original generic type parameter by the time you want
to call the ElementAt() method (from your most recent reply, it seems that
you don't), I think you'll have to use reflection to get the parameterized
type based on the type parameter of the object's IList<T> implementation,
construct a concrete generic type from that and call the
Enumerable.ElementAt() method that way.

If you are in code that knows at compile time the type of the IList<T>
object, then you can just call the method directly:

object obj = new List<Baza>();

...

IEnumerable<Baza> ebaza = (IEnumerable<Baza>)obj;

Baza baza = ebaza.ElementAt(0);

// or even more explicitly (to show the static aspect of the class):
Baza baza = Enumerable<Baza>.ElementAt(baza, 0);

Note the last line. That's all an extension method really is; it's a
special kind of static method that the compiler knows how to call even
when the code is written as if the method is an instance method on some
other type. But if you're going to be messing around with reflection, you
need to understand that it's really just a static method in the type where
the extension method is declared, not in the type where it _appears_ to be
when written as an instance method call.

Pete
 
P

Peter Duniho

[...]
but than I get exception:
Object of type \"System.Collections.Generic.List`1[System.String]\" can
not
be convertet in type
\"System.Collections.Generic.IEnumerable`1[System.Object]\"

How I can List<string> cast into List<object> ?

You mean "List<String> cast into IEnumerable<object>". And, it can't, not
until .NET 4.0/C# 4.0.

So, my other comments with respect to using the Item property, or creating
the necessary IEnumerable<T> concrete type at run-time based on the input
type, would apply.

Pete
 

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