views:

184

answers:

2

I would like to write something similar to the following:

//  I will pass in a number of "properties" specified as strings that I want modified
string[] properties = new [] { "AllowEdit", "AllowDelete" };

//  Casting the component I'm using to a dynamic object of some sort ?
dynamic d = myGridComponent;

//  Iterate over the strings and set the properties
foreach(var s in properties) 
{
  //d.s = true; // 
  //d[s] = true; // this format would be ideal
}

I was wondering if there was an easy way to do this without using Reflection [.GetProperty(...).GetValue(...,...)] using the new C# 4.0 keyword: dynamic.

It seems that there may be some way, ... I'm just not sure of the exact mechanism, and haven't been able to find the right resource to put all the pieces together.

Thoughts ?

+3  A: 

No. dynamic in C# doesn't offer that. With your two examples:

d.s = true; // this looks for a property or field called "s"
d[s] = true; // this looks for an indexer that matches the string/bool signature

You can write the same code that dynamic offers, but it would be a lot harder than just using reflection. Either use reflection (as per your example), or if you need to optimise it you can optionally wrap it in a delegate, via either Expression or Delegate.CreateDelegate.

Marc Gravell
Did not think so, but worth asking! Definitely one feature I miss from PHP.. of course, at least there *are* ways of doing it, just thought it would be nice if dynamic objects could be accessed via Indexer. :)- Matthew
Matthew M.
+1  A: 

It can be done. You just have to override TryGetIndex on DynamicObject. I needed something similar to invoke static members of a type, but hopefully you will get the idea. Mind you this does not currently work on methods with generic type arguments or methods that are overloaded, limiting its utility:

        internal class StaticMembersDynamicWrapper : DynamicObject
            {
                private readonly IDictionary<String, MemberInfo> staticMembers = new Dictionary<string, MemberInfo>();
                private readonly Type type;

                public StaticMembersDynamicWrapper(Type type)
                {
                    this.type = type;
                    type.GetMembers(BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public)
                        .Each(member => staticMembers[member.Name] = member);
                }

                public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
                {
                    var name = indexes[0] as string;

                    MemberInfo member;

                    if (false == staticMembers.TryGetValue(name, out member))
                    {
                        result = null;
                        return false;
                    }

                    var prop = member as PropertyInfo;
                    if (prop != null)
                    {
                        result = prop.GetValue(null, null);
                        return true;
                    }
                    var method = member as MethodInfo;
                    if (method != null)
                    {
                        var parameterTypes = (from p in method.GetParameters()
                                              select p.ParameterType).ToArray();
                        var delegateType = method.ReturnType != typeof (void)
                                        ? Expression.GetFuncType(parameterTypes.Union(new[]{method.ReturnType}).ToArray())
                                        : Expression.GetActionType(parameterTypes);
                        result = Delegate.CreateDelegate(delegateType, method);
                        return true;
                    }
                    result = null;
                    return false;
                }
    }
dynamic d = new StaticMembersDynamicWrapper(typeof(string));
var result = d["IsNullOrEmpty"](String.Empty);
João Bragança