12

我想写一些类似下面的东西:

//  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
}

我想知道是否有一种简单的方法可以在不使用反射 [ .GetProperty(...).GetValue(...,...)] 的情况下使用新的 C# 4.0 关键字:dynamic.

似乎可能有某种方式,......我只是不确定确切的机制,并且无法找到合适的资源来将所有部分放在一起。

想法?

[编辑] 看起来有一个名为“Clay”的包以某种方式实现了这种类型的功能。 Clay on CodePlex
Scott Hanselman 谈主题

4

3 回答 3

6

可以办到。你只需要覆盖TryGetIndexon DynamicObject。我需要类似的东西来调用一个类型的静态成员,但希望你能明白。请注意,这目前不适用于具有泛型类型参数的方法或重载的方法,从而限制了它的实用性:

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);
于 2010-08-13T23:52:51.503 回答
3

C# 中的不dynamic提供。用你的两个例子:

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

可以编写dynamic提供的相同代码,但这比仅使用反射要困难得多。使用反射(根据您的示例),或者如果您需要优化它,您可以选择将其包装在委托中,通过ExpressionDelegate.CreateDelegate

于 2010-05-06T18:37:12.577 回答
2

通过 nuget 可用的开源框架Impromptu-interface封装了 dynamic 将以完全动态的方式生成的代码。它不如使用 dynamic 关键字快,但比反射快

foreach(var s in properties) 
{
  //d.s = true; 
  Impromptu.InvokeSet(d, s, true);
}
于 2011-07-18T19:03:14.553 回答