P
Patrick Ireland
I am dynamically loading a class. One of the methods of the class takes
a short * (by reference) argument. However, the InvokeMember call used
to invoke the method of the class passings arguments in and object [].
Since this is a pointer reference being passed it must be invoked in a
unsafe {} even thought the dynamically loaded class is a .Net entity.
The following is the test code that I am using to try and load a short *
into an object:
using System;
using System.Reflection;
namespace TestBoxing
{
class TestBoxing
{
[STAThread]
static void Main(string[] args)
{
Object MyObj;
Int16 MyVar = 1;
unsafe
{
System.Int16 * pVar = &MyVar;
MyObj = Pointer.Box(pVar,typeof(System.Int16 *));
Console.WriteLine("Type {0}",MyObj.GetType());
} // unsafe
} // static void Main ()
} // class TestBoxing
} // namespace TestBoxing
A more complete tester for reflection and trying to use InvokeMember is
as follows:
using System;
using System.Reflection;
namespace TestByReference
{
class MyClass
{
public void MyMethod (ref short MyParm)
{
MyParm = 6;
} // public void MyMethod ()
} // class MyClass
class TestByReference
{
[STAThread]
static void Main(string[] args)
{
try
{
// Normal invocation
MyClass MyObj = new MyClass();
short MyArg = 5;
Console.WriteLine("MyArg {0}",MyArg);
MyObj.MyMethod(ref MyArg);
Console.WriteLine("MyArg {0}",MyArg);
// InvokeMember
Type MyType = MyObj.GetType();
Console.WriteLine("MT {0}",MyType.FullName);
MethodInfo [] MyInfos = MyType.GetMethods();
Console.WriteLine("# MIs {0}",MyInfos.Length);
foreach(MethodInfo mInfo in MyInfos)
Console.WriteLine("Method {0}",mInfo.Name);
Console.WriteLine("MI[3] {0}",MyInfos[3].Name);
ParameterInfo [] MyParms;
MyParms = MyInfos[3].GetParameters();
Console.WriteLine("# MPs {0}",MyParms.Length);
Console.WriteLine("Type of Parmeter {0}",
MyParms[0].ParameterType);
object [] MyCallingArgs = new object [1];
unsafe
{
MyCallingArgs[0] = Pointer.Box(&MyArg,typeof(System.Int16 *));
Console.WriteLine("MyCallingArs[0] type
{0}",MyCallingArgs[0].GetType());
MyType.InvokeMember("MyMethod",
BindingFlags.InvokeMethod |
BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance,
null,
MyObj,
MyCallingArgs);
} // unsafe
Console.WriteLine("MyArg {0}",MyArg);
} // try
catch (Exception ex)
{
Console.WriteLine(ex.Message);
} // catch (Exception ex)
} // static void Main ()
} // class TestByReference
} // namespace TestByReference
As a finally comment on my question - if you examine the underlying il
code the C# invocation does a boxing of the short *, but attempting to
use the InvokeMember can not construct the required argument list.
a short * (by reference) argument. However, the InvokeMember call used
to invoke the method of the class passings arguments in and object [].
Since this is a pointer reference being passed it must be invoked in a
unsafe {} even thought the dynamically loaded class is a .Net entity.
The following is the test code that I am using to try and load a short *
into an object:
using System;
using System.Reflection;
namespace TestBoxing
{
class TestBoxing
{
[STAThread]
static void Main(string[] args)
{
Object MyObj;
Int16 MyVar = 1;
unsafe
{
System.Int16 * pVar = &MyVar;
MyObj = Pointer.Box(pVar,typeof(System.Int16 *));
Console.WriteLine("Type {0}",MyObj.GetType());
} // unsafe
} // static void Main ()
} // class TestBoxing
} // namespace TestBoxing
A more complete tester for reflection and trying to use InvokeMember is
as follows:
using System;
using System.Reflection;
namespace TestByReference
{
class MyClass
{
public void MyMethod (ref short MyParm)
{
MyParm = 6;
} // public void MyMethod ()
} // class MyClass
class TestByReference
{
[STAThread]
static void Main(string[] args)
{
try
{
// Normal invocation
MyClass MyObj = new MyClass();
short MyArg = 5;
Console.WriteLine("MyArg {0}",MyArg);
MyObj.MyMethod(ref MyArg);
Console.WriteLine("MyArg {0}",MyArg);
// InvokeMember
Type MyType = MyObj.GetType();
Console.WriteLine("MT {0}",MyType.FullName);
MethodInfo [] MyInfos = MyType.GetMethods();
Console.WriteLine("# MIs {0}",MyInfos.Length);
foreach(MethodInfo mInfo in MyInfos)
Console.WriteLine("Method {0}",mInfo.Name);
Console.WriteLine("MI[3] {0}",MyInfos[3].Name);
ParameterInfo [] MyParms;
MyParms = MyInfos[3].GetParameters();
Console.WriteLine("# MPs {0}",MyParms.Length);
Console.WriteLine("Type of Parmeter {0}",
MyParms[0].ParameterType);
object [] MyCallingArgs = new object [1];
unsafe
{
MyCallingArgs[0] = Pointer.Box(&MyArg,typeof(System.Int16 *));
Console.WriteLine("MyCallingArs[0] type
{0}",MyCallingArgs[0].GetType());
MyType.InvokeMember("MyMethod",
BindingFlags.InvokeMethod |
BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance,
null,
MyObj,
MyCallingArgs);
} // unsafe
Console.WriteLine("MyArg {0}",MyArg);
} // try
catch (Exception ex)
{
Console.WriteLine(ex.Message);
} // catch (Exception ex)
} // static void Main ()
} // class TestByReference
} // namespace TestByReference
As a finally comment on my question - if you examine the underlying il
code the C# invocation does a boxing of the short *, but attempting to
use the InvokeMember can not construct the required argument list.