views:

363

answers:

1

This is similar to Invoking a method using reflection on a singleton object but it has a much deeper context. First I want to say this is for a project I was just playing around with ideas on, this is in NO way production code, and the project has taken a VERY different path, but this problem still haunts me so here it goes.

I have a singleton that only contains object instances (which although non-static are essentially singletons as well, but referenced by the base singleton)

    static CoreInstance()
    {
        Kernel = new Kernel();
        Devices = new Devices();
        Interfaces = new Interfaces();
        Interoperability = new Interoperability();
        Environment = new Environment();
        Data = new Data();
    }

normally this would be all fine and dandy but these are themselves often container objects, for instance, I might want to do the following:

CoreInstance.Kernel.RaiseError("I'm an error lol!", ErrorLevel.Trivial);

-or-

string username = CoreInstance.Environment.User.FullName;

but I am doing this from a user command console, which is another discussion for a later SO question ;-)

so the primary question here is: How do you write a recursive reflection function to break apart a class path string like this to execute a method/evaluate a property?

NOTE: assume that the call has already been broken down into a structure containing an ordered string array for the path elements, a string for the method/property, and an object array for the parameters.

+1  A: 

Well if you have two arrays containing the property/method names and the parameters for each then I think something like this will work:

public object Execute(object target, IEnumerable<string> memberNames, IEnumerable<object[]> args)
    {
        if(memberNames.Count() == 0)
            return target;

        string currentMember = memberNames.First();
        object[] currentArgs = args.First();

        object value;

        if (currentArgs.Length == 0)
        {
            //property
            PropertyInfo pi = target.GetType().GetProperty(currentMember);
            value = pi.GetValue(target, null);
        }
        else
        {
            //method
            MethodInfo mi = target.GetType().GetMethod(currentMember);
            value = mi.Invoke(target, currentArgs);
        }

        return Execute(value, memberNames.Skip(1), args.Skip(1));
    }

So for your first example you could call it like this:

string[] members = { "Kernel", "RaiseError" };
object[][] arguments = new[]{ new object[]{}, new object[]{"I'm an error lol!", ErrorLevel.Trivial}};
Execute(CoreInstance, members, arguments);
Lee
Very close to what I meant!string[] members = { "CoreInstance", "Kernel" };string executeme = "RaiseError";object[] arguments = new object []{"I'm an error lol!", ErrorLevel.Trivial};
Firoso
OH I see why you used the [][] arguments and yeah that makes sense, good call.
Firoso