MemberInfo Invoke with out object[]

S

stic

Hi,

I'm in a middle of writing something like 'exception handler wraper'
for a set of different methodes.
The case is that I have ca. 40 methods form web servicem, with
different return values (and types), and with out parmeters. What I
want to do is to support each method call with exception (http 404,
soap exception, and other types of exceptions) and wrap it with try &
catch (a lots of catch ;-)

So I think about:
private object SafeInvoker(delegate) {
try{
retrun invoking delegate
}
catch (A){}
catch (B) {}
catch (C) {}

and so one.
}

but the delegates should be introduced for each of my webservice metod
signature (a lot of combinations.) So I leave it for:

private object SafeInvoker( System.Reflection.MethodInfo mi, object[]
inObjects ) {
try {
return mi.Invoke(this,inObjects);
}
catches..

And this seems to be quite smart solution, but then... I NEED TO handle
[OUT] parameters, and the question is - is MethodInfo.Invoke() able to
handle such a parameters (you know out object[] outObjects in the
SafeInvoker signature, and the mi.Invoke(this, outObjects); make the
"The out parameter 'outObjects' must be assigned to before control
leaves the current method" error.)

Thanks in advance...

If you have another ideas - feel free to bring these ;-)
 
S

stic

stic said:
Hi,

I'm in a middle of writing something like 'exception handler wraper'
for a set of different methodes.
The case is that I have ca. 40 methods form web servicem, with
different return values (and types), and with out parmeters. What I
want to do is to support each method call with exception (http 404,
soap exception, and other types of exceptions) and wrap it with try &
catch (a lots of catch ;-)

So I think about:
private object SafeInvoker(delegate) {
try{
retrun invoking delegate
}
catch (A){}
catch (B) {}
catch (C) {}

and so one.
}

but the delegates should be introduced for each of my webservice metod
signature (a lot of combinations.) So I leave it for:

private object SafeInvoker( System.Reflection.MethodInfo mi, object[]
inObjects ) {
try {
return mi.Invoke(this,inObjects);
}
catches..

And this seems to be quite smart solution, but then... I NEED TO handle
[OUT] parameters, and the question is - is MethodInfo.Invoke() able to
handle such a parameters (you know out object[] outObjects in the
SafeInvoker signature, and the mi.Invoke(this, outObjects); make the
"The out parameter 'outObjects' must be assigned to before control
leaves the current method" error.)

Thanks in advance...

If you have another ideas - feel free to bring these ;-)
 
N

Nicholas Paldino [.NET/C# MVP]

stic,

While in practice it seems like a good idea, you are going to have a
hell of a time creating not one, but TWO versions of each function (the one
that is publically acessible, and the one that actually performs the logic).
Additionally, creating the code to dynamically call the method with the
logic is going to give you so much overhead that it's really not worth it,
in my opinion.

Rather, I would place a try/catch block in each of your methods, and
have one generic catch block, which calls your exception handling code.

Hope this helps.
 
S

stic

Nicholas,

There is truth and wisdom in your statement, but .. ;-)

I'm doing this with web service (what I didn't mention because I want
to have clear picture). And then, what I have is a set of web service
methods, you see

public whatever SomeWebServiceVeryImportantMethod() {
string methodName =
System.Reflection.MethodInfo.GetCurrentMethod().Name;
MethodInfo mi = ws.GetType().GetMethod(methodName); //where ws is
my Web Service
//I check if this web service really has this method
if ( mi == null ) {
NullReferenceException nex =
new NullReferenceException("Web service does not
define method: "+methodName);
throw nex;
}
return this.SafeInvoker(mi, null);
}

and the SafeInvoker just take the mi and inObjects (object[])... And
wrapped call is executed mi.Invoke(ws, inObjects).
This is working, is simple, and quite fast. What is more important I
could add as much exception types as I need, and I do it only in one
method.

The second thing I do, Is a method with takes general System.Exception
ex
dispatch it, to my exception types, in a way of
if (ex is MyExceptionA) doAThings;
if(ex is MyExceptionB) doBThings

throw new Exception("",ex); - I pass the message also ;-)

And this works for [out] methods - but THERE MUST BE SIMPLER or SMARTER
way to achieve this !!!
 
N

Nicholas Paldino [.NET/C# MVP]

I can't imagine how any of this will do you any good. Your exception
handling methods can't have any specific logic in it (since they are
generic), and that's a bad thing.

Also, the following code:

string methodName =
System.Reflection.MethodInfo.GetCurrentMethod().Name;
MethodInfo mi = ws.GetType().GetMethod(methodName); //where ws is my Web
Service
//I check if this web service really has this method
if ( mi == null )
{
NullReferenceException nex = new NullReferenceException("Web service
does not define method: " + methodName);
throw nex;
}

Is REALLY uncessary. If the web service does not exist, there really
isn't a way to recover gracefully, and in the case where most of the time
where the call is going to succeed, you are wasting a ton of time using
reflection to perform an operation that means nothing.

As for the out parameters. The object array should be populated (from
the call to Invoke) with the modified parameters. Why not just assign those
values from the array back to the parameters (at least those that are ref or
out).
 
J

Jon Skeet [C# MVP]

And this seems to be quite smart solution, but then... I NEED TO handle
[OUT] parameters, and the question is - is MethodInfo.Invoke() able to
handle such a parameters (you know out object[] outObjects in the
SafeInvoker signature, and the mi.Invoke(this, outObjects); make the
"The out parameter 'outObjects' must be assigned to before control
leaves the current method" error.)

Yes, MethodInfo.Invoke handles out parameters - basically the parameter
array you pass in is updated with the appropriate values before it
exits. I didn't quite follow what you were doing, so I'm not sure how
much help it will be... Here's an example though:

using System;
using System.Reflection;

class Test
{
static void Main()
{
MethodInfo method = typeof(Test).GetMethod("Foo");

object[] args = new object[1];
method.Invoke (new Test(), args);
Console.WriteLine (args[0]);
}

public void Foo(out int x)
{
x = 5;
}
}
 
S

stic

Hi Nicholas,

Well, try to think out of box - all methods are from Web Service, if
one service does not exist what is the problem to try another service
(for example the same web service hosted by different http servers,
which IPs are on recover list).
If Web Service don't respond I always could try again after some
interval, etc... And what is more important there could be not only
typical exceptions, but a few of SOAPExceptions which need to be
handled in the specific way.
Of course if everything is going well, I just waste run-time - but if
it run smoothly all my try and catch wouldn't be necessary ;-)

Anyway I just use this method for exception type dispatching - maybe
this isn't the best methode to do it, but it is easy - and I avoided to
much reflection (because you are right about it - reflection isn't
always good).

About the [out] parameter - I just want to much. It is inpossible to do
something like this:

public void A(out typeA a){
B(out a);
}

public void B (out typeA a){
a = new typeA();
}

because I need to define variable a in the A method - simple thing
which show me that I need to get some sleep sometimes ;-)

Of course I could add some 'proxy' to the A method, and code it like
this:

public void A (out typeA a) {
a = new typeA();
B(out typeA b);
a = b;
}

but as I want to do MethodInfo.Invoke, and I need to create new objects
(object[]) before each call. And the population isn't so easy because
each call could need different types of objects. The
SafeInvoker(MethodInfo mi, out objects[] objects) - should be extended
with parametr that inform the invoker which objects[] need to created.
And that is too much :)
 
S

stic

Hi Jon,

Thanks for your example, and your answer-time.
What I wanted (and don't want anymore) is to generate general inovoker,
which takes the MethodInfo + the objects[] (where the objects[] would
be [out]) as parameters.
I simply jump over the issue that out parameter need to be created
inside the invoker. As far I don't want to pass the list of types,
which would be on the objects[] list to the invoker. What could solve
the problem, and invoker could create a list in runtime.

So I leave this idea (about invoker with takes out parameters).
 
J

Jon Skeet [C# MVP]

stic said:
About the [out] parameter - I just want to much. It is inpossible to do
something like this:

public void A(out typeA a){
B(out a);
}

public void B (out typeA a){
a = new typeA();
}

because I need to define variable a in the A method - simple thing
which show me that I need to get some sleep sometimes ;-)

No, the above works fine - here's an example.

using System;

class Test
{
static void Main()
{
int x;

A(out x);
Console.WriteLine (x);
}

public static void A(out int a)
{
B(out a);
}

public static void B (out int a)
{
a = 5;
}
}

I'm afraid I still don't really understand what you're trying to do...
 
S

stic

Hi Jon,

I'm so glad to see you in this :) I let mayself edit your code a
little to show my problem:

using System;
class Test {
int x;
public Test() { this.x = 0; }

public void Invoker( System.Reflection.MethodInfo mi, out
object[] objects){
mi.Invoke(this, objects);
}

public void A(out int x) { x = 645; }

public static void Main() {
Test test = new Test();
test.Run();
}

public void Run(){
System.Reflection.MethodInfo mi =
this.GetType().GetMethod("A");
object[] objects = new object[1] {x};
this.Invoker(mi,out objects);
Console.WriteLine( x );
Console.ReadLine();
}
}

As you see no matter what you do here if you don't create object[]
instances inside the Invoker - (I want to avoid this) You would obtain
the: "The out parameter 'objects' must be assigned to before control
leaves the current method".

Maybe that will clear it ?

once again, that for your help & time !
 
J

Jon Skeet [C# MVP]

stic said:
I'm so glad to see you in this :) I let mayself edit your code a
little to show my problem:

using System;
class Test {
int x;
public Test() { this.x = 0; }

public void Invoker( System.Reflection.MethodInfo mi, out
object[] objects){
mi.Invoke(this, objects);
}

public void A(out int x) { x = 645; }

public static void Main() {
Test test = new Test();
test.Run();
}

public void Run(){
System.Reflection.MethodInfo mi =
this.GetType().GetMethod("A");
object[] objects = new object[1] {x};
this.Invoker(mi,out objects);
Console.WriteLine( x );
Console.ReadLine();
}
}

As you see no matter what you do here if you don't create object[]
instances inside the Invoker - (I want to avoid this) You would obtain
the: "The out parameter 'objects' must be assigned to before control
leaves the current method".

Maybe that will clear it ?

I don't see why you want to make Invoker take its "objects" parameter
an out parameter. If you remove the "out" modifier from both the
declaration and the call, it'll work just fine. The way it currently
is, there would be no point in creating the new object array with the
parameter in it in the first place, as it couldn't possibly be used.

Btw, to make the code clearer in the future, it would be helpful not to
have an instance variable named the same as a parameter :)
 
S

stic

Hi,
1.
In the real world Invoker works for web service method which has out
parameters. Also each of web service method has return value, which
also has to be handled. The invoker could (but please forget about this
solution, I do it another way), invoke web service methods for the
client. On client there is a interface which has to be implemented with
the out parameters.
That is why you call method for interface with out parameter ->
This parameter is pass to invoker as out parameter ->
And during invoke the parameter should be propertly initilized and
filled by the web service.
2. The new array is ther only because I try to picture the situation.
In real example the Run signature is something like Run( out int inx)
and then you just pass the x to the Invoker. I create the new object[]
for this x parameter, because I need to encapsulate each call the the
Invoker in the out object[] - if there is better idea, please say ...
Should I rather call
Invoker(mi, out (object) x) if the x isn't global variable, but Run out
parameter?

3. Yes I know the thing about variable and parameters, always try to
avoid this, and always miss the thing. You know after the _x is
forbidden - I really don't know how to prefix the parameters well...
Any idea?

Once again, thanks for your so-in-to ...
As always the problem was solved another way, but I learn a lot... (and
still I'd I think, waiting for your answer :)
 
J

Jon Skeet [C# MVP]

stic said:
1.
In the real world Invoker works for web service method which has out
parameters. Also each of web service method has return value, which
also has to be handled. The invoker could (but please forget about this
solution, I do it another way), invoke web service methods for the
client. On client there is a interface which has to be implemented with
the out parameters.
That is why you call method for interface with out parameter ->
This parameter is pass to invoker as out parameter ->
And during invoke the parameter should be propertly initilized and
filled by the web service.

If the interface requires you to use an out parameter, you'll need to
create the array to pass to Method.Invoke, then copy back all the out
parameters you're interested in. Whether the *array* is passed as an
out parameter is entirely separate to whether each of the individual
parameters to the method is an out parameter.

I would suggest you make your Invoker method take a normal object[]
(not an out parameter) and invoke using that; the client can then look
at the values to find out the new values of any out parameters.
2. The new array is ther only because I try to picture the situation.
In real example the Run signature is something like Run( out int inx)
and then you just pass the x to the Invoker. I create the new object[]
for this x parameter, because I need to encapsulate each call the the
Invoker in the out object[] - if there is better idea, please say ...
Should I rather call
Invoker(mi, out (object) x) if the x isn't global variable, but Run out
parameter?

No, my point was that you just need:

object[] p;

Invoker (mi, out p);

The value of p is irrelevant at that point, and p doesn't need to be
definitely assigned.
3. Yes I know the thing about variable and parameters, always try to
avoid this, and always miss the thing. You know after the _x is
forbidden - I really don't know how to prefix the parameters well...
Any idea?

_x isn't forbidden at all. Personally I don't like the convention, but
it's valid.
Once again, thanks for your so-in-to ...
As always the problem was solved another way, but I learn a lot... (and
still I'd I think, waiting for your answer :)

:)
 
S

stic

If the interface requires you to use an out parameter, you'll need to
create the array to pass to Method.Invoke, then copy back all the out
parameters you're interested in. Whether the *array* is passed as an
out parameter is entirely separate to whether each of the individual
parameters to the method is an out parameter.

I would suggest you make your Invoker method take a normal object[]
(not an out parameter) and invoke using that; the client can then look
at the values to find out the new values of any out parameters.

That is the way I did it ;-) Before I invoke I just encapsulate
parameters inside the object[] and after invoking I read what I get. I
could not pass normal (not out) object[] to the Invoke because I read &
compare this object[] not in Invoke but in specific method (from which
the invoke is called).
Please remember that this Invoker have to return some other values
(ReturnCode), so I could not pass return object[] as a return from the
Invoker.
2. The new array is ther only because I try to picture the situation.
In real example the Run signature is something like Run( out int inx)
and then you just pass the x to the Invoker. I create the new object[]
for this x parameter, because I need to encapsulate each call the the
Invoker in the out object[] - if there is better idea, please say ...
Should I rather call
Invoker(mi, out (object) x) if the x isn't global variable, but Run out
parameter?

No, my point was that you just need:

object[] p;

Invoker (mi, out p);
The value of p is irrelevant at that point, and p doesn't need to be
definitely assigned.

Yes, that right... Thank you (with big objects this really make matter)
_x isn't forbidden at all. Personally I don't like the convention, but
it's valid.

Well our source code guidlines don't allow this, so this is forbidden
:(
Anyway AFAIR the FxCop also make some warnings..

I still wait for your type ! ;-)
 
J

Jon Skeet [C# MVP]

stic said:
If the interface requires you to use an out parameter, you'll need to
create the array to pass to Method.Invoke, then copy back all the out
parameters you're interested in. Whether the *array* is passed as an
out parameter is entirely separate to whether each of the individual
parameters to the method is an out parameter.

I would suggest you make your Invoker method take a normal object[]
(not an out parameter) and invoke using that; the client can then look
at the values to find out the new values of any out parameters.

That is the way I did it ;-) Before I invoke I just encapsulate
parameters inside the object[] and after invoking I read what I get. I
could not pass normal (not out) object[] to the Invoke because I read &
compare this object[] not in Invoke but in specific method (from which
the invoke is called).

Why does that mean you can't pass it in as a normal parameter? Don't
forget that arrays are reference types, so you'd still be able to see
the values which had changed in the array from the calling code.

<snip>
 

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