2010-05-06 25 views
12

我想寫出類似下面的東西:C#使用動態關鍵字來訪問通過字符串的屬性,而不反射

// 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 on CodePlex
Scott Hanselman on the Subject

回答

6

它可以做到。您只需在DynamicObject上覆蓋TryGetIndex。我需要類似的東西來調用一個類型的靜態成員,但希望你能明白這個想法。你要知道這並不目前與超載泛型類型變量或方法方法的工作,限制了它的效用:

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); 
+0

哇真酷的解決方案,我正在尋找這個確切的東西! – 2012-06-28 06:35:15

3

dynamic在C#不提供這一點。有了您的兩個例子:

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

+0

不這麼認爲,但值得一問!這絕對是我錯過了PHP的一個特性..當然,至少有*方法可以做到這一點,只是認爲如果可以通過Indexer訪問動態對象,那就好了。 :) - 馬修 – 2010-05-06 22:12:51

2

的開源框架Impromptu-interface通過的NuGet可封裝了動態會產生一個完全動態的方式的代碼。它不如使用動態關鍵字快,但是是faster than reflection

foreach(var s in properties) 
{ 
    //d.s = true; 
    Impromptu.InvokeSet(d, s, true); 
} 
+0

工作真的很棒,謝謝。 – 2011-11-21 15:57:20

相關問題