I continue to investigate issues with making explicit InvokeMember calls
(necessary when dynamically loading classes). My quest lets me use a simple
class to invoke another class's member method by normal means and by using
the InvokeMember. By examining the underlying il code with ildasm, when
attempting to pass by reference, the il code generates a box command so that
a pointer to the actual data is passed. This is clearly seen with the Normal
invocation call at the il level. However, when I try to creat a InvokeMember
call, I have been unable to load a Int16& in the object list that represents
the calling parameters. The type stored in the MyCallingArgs[0] is a
System.Reflection.Pointer rather than the desired Int16&. I am attaching the
code so that you may easily test the issue.
Any clues as to how to make the second call correctly?
using System;
using System.Reflection;
namespace TestByReference
{
class MyClass
{
public void MyMethod (ref short MyParm)
{
MyParm++;
} // 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();
foreach(MethodInfo mInfo in MyInfos)
Console.WriteLine("Method {0}",mInfo.Name);
Console.WriteLine("# MIs {0}",MyInfos.Length);
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