views:

85

answers:

1

I'm trying to use Type.InvokeMember(String, BindingFlags, Binder, Object, array[]) with the default binder.

one of the arguments to the target method in the object array is a reference type set to null. I want the method I'm invoking to instantiate the reference type so that I can continue using it. For example:

using System;

namespace ConsoleApplication6
{
    class A
    {
        public void GetReferenceType(object o)
        {
            o = new object();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            object o = null;
            A a = new A();
            Type t = typeof(A);
            t.InvokeMember("GetReferenceType", System.Reflection.BindingFlags.InvokeMethod, null, a, new object[] { o });

            if (o == null)
            {
                throw new NullReferenceException();
            }
            else
            {
                //do something with o;
            }
        }
    }
}

The workaround is to give A a Property and to access o through that.

Is there another way to do it without changing A?

+1  A: 

Okay, you need to make two changes here:

  • Make your GetReferenceType parameter ref:

    public void GetReferenceType(ref object o)
    

    You have to do this because currently your method is a no-op to the outside world. You should read my article on parameter handling in C#.

  • Use the value within the array after InvokeMember, instead of the original reference:

    A a = new A();
    Type t = typeof(A);
    object[] args = new object[] { null };
    t.InvokeMember("GetReferenceType", BindingFlags.InvokeMethod,
                   null, a, args);
    object o = args[0];
    

When you create an array e.g. with new object[] { o } that just copies the value of o into the array - it doesn't associate that array element with the o variable.

A better solution would be to make GetReferenceType return the new value, however... it's rarely a good idea to use an out or ref parameter in a void method.

Jon Skeet
I'd rather not change A (or it's method getReferenceType) though. Any other ways?
Matt Jacobsen
@Matt: No. `A.GetReferenceType` is a broken method. It's a no-op. It serves no purpose. You really need to understand why that is, to avoid getting into similar problems in the future.
Jon Skeet
Thanks to your article I understand now. Before reading that I never really saw the need for passing reference types by reference!
Matt Jacobsen
@Matt: Goodo :)
Jon Skeet