0

I am trying to write a function which can take in a URI and then map that to a function in C#. The intention is to have a single object in C# which has a number of functions or members which can be called. This would be similar to the Method Dispatcher in CherryPy.

I am most of the way there, but am stuck at grabbing the object in C# when reflecting through multiple layers. At current I have a function which will recurs through several layers of member object but this is done using types, and not the direct objects.

I find this hard to explain so hopefully the code below will clarify the issue (I have removed all error checking and the out clause).

The problem I have is that when calling MethodInfo.Invoke, I do not have the physical object reference to pass in as the first parameter.

I believe I should be able to get the object reference somehow from "fieldInfo" If somebody can tell me how to do that I believe I can complete this function.

{
 List<String> path = request.Url.AbsolutePath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries).ToList<String>();
 object[] parameters = new object[2] { request, response };
 System.Type controllerType = Controller.GetType();

 MethodInfo methodInfo = GetMethod(path, controllerType);

 methodInfo.Invoke(<I DONT HAVE THIS OBJECT>, parameters);
}

private MethodInfo GetMethod(List<String> path, System.Type type)
{
 MethodInfo methodInfo = type.GetMethod(path[0], BindingFlags.Public | BindingFlags.Instance);
 if(methodInfo != null)
 { 
  return methodInfo;
 }

 FieldInfo fieldInfo = type.GetField(path[0].ToString());

 path.RemoveAt(0);
 return GetMethod(path, fieldInfo.FieldType);
}
Luke Turner
  • 324
  • 1
  • 4
  • 22

1 Answers1

0

You cannot get the object reference from the FieldInfo. Type information including field information is metadata that is shared across all instances of the same type. If you create 100 instances of type T, to which one should the shared type information refer?

However, you state "The intention is to have a single object in C# which has a number of functions or members which can be called." Thus it sounds like the generic singleton pattern may work for you:

public static class SingletonHelper
{
    public static T GetInstance<T>() where T : class
    {
        return Singleton<T>.Instance;
    }

    public static object GetInstance(Type type) 
    {
        if (type == null)
            throw new ArgumentNullException();
        if (!type.IsClass)
            throw new InvalidOperationException();
        var genericType = typeof(Singleton<>).MakeGenericType(new Type[] { type });
        return genericType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public).GetValue(null, null);
    }
}

public class Singleton<T> where T : class
{
    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    /// <summary>
    /// Private nested class which acts as singleton class instantiator. This class should not be accessible outside <see cref="Singleton<T>"/>
    /// </summary>
    class Nested
    {
        /// <summary>
        /// Explicit static constructor to tell C# compiler not to mark type as beforefieldinit
        /// </summary>
        static Nested()
        {
        }

        /// <summary>
        /// Static instance variable
        /// </summary>
        internal static readonly T instance = (T)Activator.CreateInstance(typeof(T), true);
    }        

    public static T Instance { get { return Nested.instance; } }
}

Here you would call SingletonHelper.GetInstance(type). This requires that your code be working with only one AppDomain. If not, this won't work.

dbc
  • 104,963
  • 20
  • 228
  • 340