views:

95

answers:

3
        var property = obj.GetType().GetProperty(blockName);

        if (property == null)
        {
            var method = obj.GetType().GetMethod(blockName);

            if (method == null)
                return "[" + blockName + "]";
            else
                return method.Invoke(obj, null).ToString();
        }
        else
            return property.GetValue(obj, null).ToString();

This code should look for a property named blockName's value. If the property found, it should return its value. If not, it should look for function named blockName's value. If it finds, it should call it and return the returned value. If it dosen't find the method, it should return [blockName's value].

It's working great, but I'm looking for ways to make it more efficient. I don't want to convert methods to properties or properties to methods, because in the future I'll add parameters too. Can you help me please?

Thanks.

+2  A: 

One method to do this is to emit a dynamic method the first time this code is executed, and cache it. Then, subsequent calls execute the pregenerated method, which ends up being pretty fast. If repeatedly executing this code is the problem you're seeing, then this approach may work well for you. And please forgive me if I'm butchering the explanation.

Have a look at the Dynamic Reflection Library on codeplex.

Nader Shirazie
+2  A: 

Your main problem is that Type.GetProperty(...) and Type.GetMethod(...) are extremely slow. Cache the values returned from these methods and you'll see a huge speedup (like 20x faster for this code).

Although MethodInfo.Invoke and PropertyInfo.GetValue are slower than direct calls, they are plenty fast for most purposes. Only optimize them using dynamic assemblies if you really have to - it's a lot of work.

Ray Burns
+1 for highlighting `GetProperty` and `GetMethod` as being more responsible for perf issues.
Nader Shirazie
+3  A: 

If you know the signatures (i.e. the return type and parameters), then Delegate.CreateDelegate can be used very effectively here:

using System;
using System.Reflection;
class Test
{
    public string Foo(int i)
    {
        return i.ToString();
    }
    static void Main()
    {
        MethodInfo method = typeof(Test).GetMethod("Foo");
        Func<Test, int, string> func = (Func<Test, int, string>)
            Delegate.CreateDelegate(typeof(Func<Test, int, string>), null, method);
        Test t = new Test();
        string s = func(t, 123);

    }
}

Note that for properties, you want to look at GetGetMethod and GetSetMethod. This doesn't work so well if you don't know the signature, as DynamicInvoke is very slow.

To get benefit from Delegate.CreateDelegate, you must cache and re-use the delegate instance; don't recreate it each time!

For properties, even if you don't know the property-type, then perhaps consider HyperDescriptor (you need to add the 1-line to enable hyper-descriptor):

using System.ComponentModel;
class Test
{
    public int Bar { get; set; }
    static void Main()
    {
        PropertyDescriptor prop = TypeDescriptor.GetProperties(
            typeof(Test))["Bar"];
        Test t = new Test();
        t.Bar = 123;
        object val = prop.GetValue(t);
    }
}
Marc Gravell