How to return reference arguement using InvokeMember?

M

Mike

Using Type.InvokeMember to call a method of a class,Which
method has reference arguement,It is seemed that there is
no way to return the changed value of that reference
arguement by the method of the class.
Who can save me?
Thanks a lot!
 
J

Jon Skeet [C# MVP]

Mike said:
Using Type.InvokeMember to call a method of a class,Which
method has reference arguement,It is seemed that there is
no way to return the changed value of that reference
arguement by the method of the class.

The changed value will be present in the array that you passed in. So,
you'd do:

object[] parameters = ...;
// Invoke the member here, using "parameters" as the parameters array

// parameters now contains the modified values
 
E

Elder Hyde

Jon, just curious but... do you sleep at all? I've been following this
newsgroup for a couple of days and I've begun to suspect that you're a
bot or something ;)

Elder
 
J

Jon Skeet [C# MVP]

Jon, just curious but... do you sleep at all? I've been following this
newsgroup for a couple of days and I've begun to suspect that you're a
bot or something ;)

Let's just say that I have a 6 week old baby :)
 
M

Mike

Thanks for your response.
But, if the called method is in a COM class,the modified
value of that reference parameter can't be returned via
the parameter array!
What can I do? Whther I must use "ParameterModifier"?and
how to use it?

An early reply will be appreciated.
-----Original Message-----
Mike said:
Using Type.InvokeMember to call a method of a class,Which
method has reference arguement,It is seemed that there is
no way to return the changed value of that reference
arguement by the method of the class.

The changed value will be present in the array that you passed in. So,
you'd do:

object[] parameters = ...;
// Invoke the member here, using "parameters" as the parameters array

// parameters now contains the modified values

--
Jon Skeet - <[email protected]>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
.
 
G

Guest

Thanks for your response.But your approach can't work in
some case.

For example,
an COM class named myclass ,it has a method named
mymethod an its VB code is like this:

Public Class myClass
Public Function mymethod(ByVal a As Integer, ByVal b
As Integer, ByRef c As Integer) As Integer
c = a - b
Return a + b
End Function
End Class

The class has been compiled into a COM dll named
myTest.dll,then use it in VB.NET,like this:

Dim Aobj() As Object = {15, 6, 3}
MsgBox(Aobj(2))
Dim obj As New myTest.myclass()
Dim T As Type = Type.GetTypeFromProgID("myTest.myclass")
dim d as object
d= T.InvokeMember("mymethod",
Reflection.BindingFlags.Public Or
Reflection.BindingFlags.InvokeMethod Or
Reflection.BindingFlags.Instance, Nothing, obj, Aobj)
MsgBox(Aobj(2))
MsgBox(d)

IN the code,the desired value of Aobj(2) is 9,but it
remains 3.
what shall I do ? Whther I must use "ParameterModifier"?
and how to use it?

An early reply will be appreciated.
-----Original Message-----
Mike said:
Using Type.InvokeMember to call a method of a class,Which
method has reference arguement,It is seemed that there is
no way to return the changed value of that reference
arguement by the method of the class.

The changed value will be present in the array that you passed in. So,
you'd do:

object[] parameters = ...;
// Invoke the member here, using "parameters" as the parameters array

// parameters now contains the modified values

--
Jon Skeet - <[email protected]>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
.
 
J

Jon Skeet [C# MVP]

Thanks for your response.But your approach can't work in
some case.

For example,
an COM class named myclass ,it has a method named
mymethod an its VB code is like this:

<snip>

Are you absolutely sure that your code is working correctly in the
first place? What happens if you make a static call, just calling the
method directly rather than with reflection?
 
M

mike

In my application,the name of the method member is
variational,and it is stored in a variable,so it is not
allowed the method to be called directly. I use
reflection to call it.
 
J

Jon Skeet [C# MVP]

mike said:
In my application,the name of the method member is
variational,and it is stored in a variable,so it is not
allowed the method to be called directly. I use
reflection to call it.

Yes, but in order to find out what's going wrong it's worth using a
static call to start with. Test with the simplest thing you can, then
when you've got that working, make it more complicated etc until it
does everything you need to.
 
W

Willy Denoyette [MVP]

You have to pass the third arg by ref using a ParameterModifier array.

Here is how you should do it in C#

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] pmods = { pm };

object retVal = obj.GetType().InvokeMember(methodName,
BindingFlags.InvokeMethod, null, obj , args, pmods, null, null);

Willy.

Thanks for your response.But your approach can't work in
some case.

For example,
an COM class named myclass ,it has a method named
mymethod an its VB code is like this:

Public Class myClass
Public Function mymethod(ByVal a As Integer, ByVal b
As Integer, ByRef c As Integer) As Integer
c = a - b
Return a + b
End Function
End Class

The class has been compiled into a COM dll named
myTest.dll,then use it in VB.NET,like this:

Dim Aobj() As Object = {15, 6, 3}
MsgBox(Aobj(2))
Dim obj As New myTest.myclass()
Dim T As Type = Type.GetTypeFromProgID("myTest.myclass")
dim d as object
d= T.InvokeMember("mymethod",
Reflection.BindingFlags.Public Or
Reflection.BindingFlags.InvokeMethod Or
Reflection.BindingFlags.Instance, Nothing, obj, Aobj)
MsgBox(Aobj(2))
MsgBox(d)

IN the code,the desired value of Aobj(2) is 9,but it
remains 3.
what shall I do ? Whther I must use "ParameterModifier"?
and how to use it?

An early reply will be appreciated.
-----Original Message-----
Mike said:
Using Type.InvokeMember to call a method of a class,Which
method has reference arguement,It is seemed that there is
no way to return the changed value of that reference
arguement by the method of the class.

The changed value will be present in the array that you passed in. So,
you'd do:

object[] parameters = ...;
// Invoke the member here, using "parameters" as the parameters array

// parameters now contains the modified values

--
Jon Skeet - <[email protected]>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
.
 
M

mike

hello,Willy,

I followed your guidance,but exception happened.
My calling code in c# is as folloow:

object [] args={12, 3, 5};
myTest.myclass obj=new heTest.myclass();
Type T=Type.GetTypeFromProgID("heTest.myclass");

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] pmods = { pm };

object d = T.InvokeMember("method",
BindingFlags.InvokeMethod, null, obj, args, pmods, null,
null);

Would you please select a COM dll and have a try by
yourself?
Thanks a lot.

-----Original Message-----
You have to pass the third arg by ref using a ParameterModifier array.

Here is how you should do it in C#

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] pmods = { pm };

object retVal = obj.GetType().InvokeMember(methodName,
BindingFlags.InvokeMethod, null, obj , args, pmods, null, null);

Willy.

Thanks for your response.But your approach can't work in
some case.

For example,
an COM class named myclass ,it has a method named
mymethod an its VB code is like this:

Public Class myClass
Public Function mymethod(ByVal a As Integer, ByVal b
As Integer, ByRef c As Integer) As Integer
c = a - b
Return a + b
End Function
End Class

The class has been compiled into a COM dll named
myTest.dll,then use it in VB.NET,like this:

Dim Aobj() As Object = {15, 6, 3}
MsgBox(Aobj(2))
Dim obj As New myTest.myclass()
Dim T As Type = Type.GetTypeFromProgID ("myTest.myclass")
dim d as object
d= T.InvokeMember("mymethod",
Reflection.BindingFlags.Public Or
Reflection.BindingFlags.InvokeMethod Or
Reflection.BindingFlags.Instance, Nothing, obj, Aobj)
MsgBox(Aobj(2))
MsgBox(d)

IN the code,the desired value of Aobj(2) is 9,but it
remains 3.
what shall I do ? Whther I must use "ParameterModifier"?
and how to use it?

An early reply will be appreciated.
-----Original Message-----
Using Type.InvokeMember to call a method of a class,Which
method has reference arguement,It is seemed that
there
is
no way to return the changed value of that reference
arguement by the method of the class.

The changed value will be present in the array that
you
passed in. So,
you'd do:

object[] parameters = ...;
// Invoke the member here, using "parameters" as the parameters array

// parameters now contains the modified values

--
Jon Skeet - <[email protected]>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
.


.
 
W

Willy Denoyette [MVP]

Mike,
That's what I did :)
Here's my code:

<C# snippet>
int i1 = 15;
int i2 = 6;
int i3 = 3;
Type type = Type.GetTypeFromProgID("simple.Tester"); // ProgID
object obj = Activator.CreateInstance(type);
string methodName = "MyMethod";
object[] args = new object[3];
args[0] = i1;
args[1] = i2;
args[2] = i3;
// Modify third arg. and pass it byref
ParameterModifier pm = new ParameterModifier(3);
pm[0] = false; // LONG
pm[1] = false; // LONG
pm[2] = true; // byref (type is LONG*)
ParameterModifier [] mods = { pm };
object retVal = obj.GetType().InvokeMember(methodName,
BindingFlags.InvokeMethod, null, obj , args, mods, null, null);
Console.WriteLine("Values : retval={0} i3={1}",retVal, args[2]);
.....
</end of C#>

Here's the IDL (COM object written in C++)
....
[
object,
uuid(EA461F01-8209-41CB-869C-111220E83CB3),
dual,
helpstring("ITester Interface"),
pointer_default(unique)
]
interface ITester : IDispatch {
[id(1),helpstring("method MyMethod")] HRESULT MyMethod([in]LONG i1,
[in]LONG i2, [in,out] LONG *i3, [out,retval] LONG *SomeReturn);
};

Here's the output:
Values : retval=21 i3=9


What exception is thrown on you?

Willy.

mike said:
hello,Willy,

I followed your guidance,but exception happened.
My calling code in c# is as folloow:

object [] args={12, 3, 5};
myTest.myclass obj=new heTest.myclass();
Type T=Type.GetTypeFromProgID("heTest.myclass");

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] pmods = { pm };

object d = T.InvokeMember("method",
BindingFlags.InvokeMethod, null, obj, args, pmods, null,
null);

Would you please select a COM dll and have a try by
yourself?
Thanks a lot.

-----Original Message-----
You have to pass the third arg by ref using a ParameterModifier array.

Here is how you should do it in C#

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] pmods = { pm };

object retVal = obj.GetType().InvokeMember(methodName,
BindingFlags.InvokeMethod, null, obj , args, pmods, null, null);

Willy.
 
M

Mike

Dear Willy,

The problem bother me badly,Now it seems that only
you can save me.

My COM DLL was developed in VB6 and I need to use it
in .NET . so here I test the simple COM DLL Wrote by VB6
rather than VC.Following your guidance,the error still
occurs,the exception
is "System.Reflection.TargetInvocationException in
mscorlib.dll".Now I list my code.
----------------------------------------
----------------------------------------
the tested COM DLL in VB6,
ProgID is: MySimpleTest.TestClass
method code:
-----------
Public Function mymethod(ByVal a As Integer, ByVal b As
Integer, ByRef c As Integer) As Integer
mymethod = a + b
c = a - b
End Function
----------------------------------------
----------------------------------------
the calling code in c# is:
-------------------------
{
int i1 = 15;
int i2 = 6;
int i3 = 3;
object[] args ={i1,i2,i3};
MessageBox.Show(args[2].ToString(), "value of args[2]",
MessageBoxButtons.OK, MessageBoxIcon.None);

Type T=Type.GetTypeFromProgID("MySimpleTest.TestClass");
object obj = Activator.CreateInstance(T);
string methodName = "mymethod";

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] mods = { pm };

object retVal=obj.GetType().InvokeMember
(methodName,BindingFlags.InvokeMethod, null, obj , args,
mods, null, null); // error occurs!

MessageBox.Show(retVal.ToString(), "result",
MessageBoxButtons.OK, MessageBoxIcon.None);
MessageBox.Show(args[2].ToString(), "value of args[0]",
MessageBoxButtons.OK, MessageBoxIcon.None);
}
----------------------------------------------------
----------------------------------------------------
Excuting the calling,error still occurs.

Would you please test a VB6 DLL ?

I ask for your help.
I'm sorry to bother you again.

Mike.




-----Original Message-----
Mike,
That's what I did :)
Here's my code:

<C# snippet>
int i1 = 15;
int i2 = 6;
int i3 = 3;
Type type = Type.GetTypeFromProgID
("simple.Tester"); // ProgID
object obj = Activator.CreateInstance(type);
string methodName = "MyMethod";
object[] args = new object[3];
args[0] = i1;
args[1] = i2;
args[2] = i3;
// Modify third arg. and pass it byref
ParameterModifier pm = new ParameterModifier(3);
pm[0] = false; // LONG
pm[1] = false; // LONG
pm[2] = true; // byref (type is LONG*)
ParameterModifier [] mods = { pm };
object retVal = obj.GetType().InvokeMember(methodName,
BindingFlags.InvokeMethod, null, obj , args, mods, null, null);
Console.WriteLine("Values : retval={0} i3= {1}",retVal, args[2]);
.....
</end of C#>

Here's the IDL (COM object written in C++)
....
[
object,
uuid(EA461F01-8209-41CB-869C-111220E83CB3),
dual,
helpstring("ITester Interface"),
pointer_default(unique)
]
interface ITester : IDispatch {
[id(1),helpstring("method MyMethod")] HRESULT MyMethod ([in]LONG i1,
[in]LONG i2, [in,out] LONG *i3, [out,retval] LONG *SomeReturn);
};

Here's the output:
Values : retval=21 i3=9


What exception is thrown on you?

Willy.

hello,Willy,

I followed your guidance,but exception happened.
My calling code in c# is as folloow:

object [] args={12, 3, 5};
myTest.myclass obj=new heTest.myclass();
Type T=Type.GetTypeFromProgID("heTest.myclass");

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] pmods = { pm };

object d = T.InvokeMember("method",
BindingFlags.InvokeMethod, null, obj, args, pmods, null,
null);

Would you please select a COM dll and have a try by
yourself?
Thanks a lot.

-----Original Message-----
You have to pass the third arg by ref using a ParameterModifier array.

Here is how you should do it in C#

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] pmods = { pm };

object retVal = obj.GetType().InvokeMember (methodName,
BindingFlags.InvokeMethod, null, obj , args, pmods, null, null);

Willy.


.
 
W

Willy Denoyette [MVP]

Now I see, your problem is that VB6 int's are short's in .NET (C# and
VB.NET).
so i1, i2, i3 and the return value are 16 bit short values!!!

Willy.

Mike said:
Dear Willy,

The problem bother me badly,Now it seems that only
you can save me.

My COM DLL was developed in VB6 and I need to use it
in .NET . so here I test the simple COM DLL Wrote by VB6
rather than VC.Following your guidance,the error still
occurs,the exception
is "System.Reflection.TargetInvocationException in
mscorlib.dll".Now I list my code.
----------------------------------------
----------------------------------------
the tested COM DLL in VB6,
ProgID is: MySimpleTest.TestClass
method code:
-----------
Public Function mymethod(ByVal a As Integer, ByVal b As
Integer, ByRef c As Integer) As Integer
mymethod = a + b
c = a - b
End Function
----------------------------------------
----------------------------------------
the calling code in c# is:
-------------------------
{
int i1 = 15;
int i2 = 6;
int i3 = 3;
object[] args ={i1,i2,i3};
MessageBox.Show(args[2].ToString(), "value of args[2]",
MessageBoxButtons.OK, MessageBoxIcon.None);

Type T=Type.GetTypeFromProgID("MySimpleTest.TestClass");
object obj = Activator.CreateInstance(T);
string methodName = "mymethod";

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] mods = { pm };

object retVal=obj.GetType().InvokeMember
(methodName,BindingFlags.InvokeMethod, null, obj , args,
mods, null, null); // error occurs!

MessageBox.Show(retVal.ToString(), "result",
MessageBoxButtons.OK, MessageBoxIcon.None);
MessageBox.Show(args[2].ToString(), "value of args[0]",
MessageBoxButtons.OK, MessageBoxIcon.None);
}
----------------------------------------------------
----------------------------------------------------
Excuting the calling,error still occurs.

Would you please test a VB6 DLL ?

I ask for your help.
I'm sorry to bother you again.

Mike.




-----Original Message-----
Mike,
That's what I did :)
Here's my code:

<C# snippet>
int i1 = 15;
int i2 = 6;
int i3 = 3;
Type type = Type.GetTypeFromProgID
("simple.Tester"); // ProgID
object obj = Activator.CreateInstance(type);
string methodName = "MyMethod";
object[] args = new object[3];
args[0] = i1;
args[1] = i2;
args[2] = i3;
// Modify third arg. and pass it byref
ParameterModifier pm = new ParameterModifier(3);
pm[0] = false; // LONG
pm[1] = false; // LONG
pm[2] = true; // byref (type is LONG*)
ParameterModifier [] mods = { pm };
object retVal = obj.GetType().InvokeMember(methodName,
BindingFlags.InvokeMethod, null, obj , args, mods, null, null);
Console.WriteLine("Values : retval={0} i3= {1}",retVal, args[2]);
.....
</end of C#>

Here's the IDL (COM object written in C++)
....
[
object,
uuid(EA461F01-8209-41CB-869C-111220E83CB3),
dual,
helpstring("ITester Interface"),
pointer_default(unique)
]
interface ITester : IDispatch {
[id(1),helpstring("method MyMethod")] HRESULT MyMethod ([in]LONG i1,
[in]LONG i2, [in,out] LONG *i3, [out,retval] LONG *SomeReturn);
};

Here's the output:
Values : retval=21 i3=9


What exception is thrown on you?

Willy.

hello,Willy,

I followed your guidance,but exception happened.
My calling code in c# is as folloow:

object [] args={12, 3, 5};
myTest.myclass obj=new heTest.myclass();
Type T=Type.GetTypeFromProgID("heTest.myclass");

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] pmods = { pm };

object d = T.InvokeMember("method",
BindingFlags.InvokeMethod, null, obj, args, pmods, null,
null);

Would you please select a COM dll and have a try by
yourself?
Thanks a lot.


-----Original Message-----
You have to pass the third arg by ref using a
ParameterModifier array.

Here is how you should do it in C#

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] pmods = { pm };

object retVal = obj.GetType().InvokeMember (methodName,
BindingFlags.InvokeMethod, null, obj , args, pmods,
null, null);

Willy.


.
 
M

Mike

With your warmhearted help,I resolve the problem
eventually.
Thanks a lot.
Would you mind my posting to your Email directly when I
encounter difficulty later?

With best regards.
Mike
-----Original Message-----
Now I see, your problem is that VB6 int's are short's in .NET (C# and
VB.NET).
so i1, i2, i3 and the return value are 16 bit short values!!!

Willy.

Dear Willy,

The problem bother me badly,Now it seems that only
you can save me.

My COM DLL was developed in VB6 and I need to use it
in .NET . so here I test the simple COM DLL Wrote by VB6
rather than VC.Following your guidance,the error still
occurs,the exception
is "System.Reflection.TargetInvocationException in
mscorlib.dll".Now I list my code.
----------------------------------------
----------------------------------------
the tested COM DLL in VB6,
ProgID is: MySimpleTest.TestClass
method code:
-----------
Public Function mymethod(ByVal a As Integer, ByVal b As
Integer, ByRef c As Integer) As Integer
mymethod = a + b
c = a - b
End Function
----------------------------------------
----------------------------------------
the calling code in c# is:
-------------------------
{
int i1 = 15;
int i2 = 6;
int i3 = 3;
object[] args ={i1,i2,i3};
MessageBox.Show(args[2].ToString(), "value of args[2]",
MessageBoxButtons.OK, MessageBoxIcon.None);

Type T=Type.GetTypeFromProgID ("MySimpleTest.TestClass");
object obj = Activator.CreateInstance(T);
string methodName = "mymethod";

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] mods = { pm };

object retVal=obj.GetType().InvokeMember
(methodName,BindingFlags.InvokeMethod, null, obj , args,
mods, null, null); // error occurs!

MessageBox.Show(retVal.ToString(), "result",
MessageBoxButtons.OK, MessageBoxIcon.None);
MessageBox.Show(args[2].ToString(), "value of args[0]",
MessageBoxButtons.OK, MessageBoxIcon.None);
}
----------------------------------------------------
----------------------------------------------------
Excuting the calling,error still occurs.

Would you please test a VB6 DLL ?

I ask for your help.
I'm sorry to bother you again.

Mike.




-----Original Message-----
Mike,
That's what I did :)
Here's my code:

<C# snippet>
int i1 = 15;
int i2 = 6;
int i3 = 3;
Type type = Type.GetTypeFromProgID
("simple.Tester"); // ProgID
object obj = Activator.CreateInstance(type);
string methodName = "MyMethod";
object[] args = new object[3];
args[0] = i1;
args[1] = i2;
args[2] = i3;
// Modify third arg. and pass it byref
ParameterModifier pm = new ParameterModifier(3);
pm[0] = false; // LONG
pm[1] = false; // LONG
pm[2] = true; // byref (type is LONG*)
ParameterModifier [] mods = { pm };
object retVal = obj.GetType().InvokeMember (methodName,
BindingFlags.InvokeMethod, null, obj , args, mods,
null,
null);
Console.WriteLine("Values : retval={0} i3= {1}",retVal, args[2]);
.....
</end of C#>

Here's the IDL (COM object written in C++)
....
[
object,
uuid(EA461F01-8209-41CB-869C-111220E83CB3),
dual,
helpstring("ITester Interface"),
pointer_default(unique)
]
interface ITester : IDispatch {
[id(1),helpstring("method MyMethod")] HRESULT
MyMethod
([in]LONG i1,
[in]LONG i2, [in,out] LONG *i3, [out,retval] LONG *SomeReturn);
};

Here's the output:
Values : retval=21 i3=9


What exception is thrown on you?

Willy.

hello,Willy,

I followed your guidance,but exception happened.
My calling code in c# is as folloow:

object [] args={12, 3, 5};
myTest.myclass obj=new heTest.myclass();
Type T=Type.GetTypeFromProgID("heTest.myclass");

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] pmods = { pm };

object d = T.InvokeMember("method",
BindingFlags.InvokeMethod, null, obj, args, pmods, null,
null);

Would you please select a COM dll and have a try by
yourself?
Thanks a lot.


-----Original Message-----
You have to pass the third arg by ref using a
ParameterModifier array.

Here is how you should do it in C#

ParameterModifier pm = new ParameterModifier(3);
pm[0] = false;
pm[1] = false;
pm[2] = true;
ParameterModifier [] pmods = { pm };

object retVal = obj.GetType().InvokeMember (methodName,
BindingFlags.InvokeMethod, null, obj , args, pmods,
null, null);

Willy.


.


.
 

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