2014-11-02 34 views
0

一個我喜歡的Python的事情就是這樣,你可以customize attribute accessC#相當於Python中的屬性定製/ JavaScript對象字面

class Foo(object): 
    def __getattr__(self, name): 
     if some_predicate(name): 
      # ... 
     else: 
      # Default behaviour 
      raise AttributeError 

你可以更直接地與JavaScript的對象文字符號類似的東西。

我的問題是:你怎麼能在C#中實現類似的東西?重載'。'運營商將如何做這件事,但它不是在允許

那種事情的一個例子,我心目中是定義一個類,如:

public class MyClass 
{ 
    public IDictionary Properties {get; private set;} 
    public MyClass(IDictionary properties) 
    { 
     this.Properties = properties; 
    } 

    // Overload the '.' operator - not allowed! 
    public static object operator .(MyClass inst, string name) 
    { 
     return inst.Properties[name]; 
    } 
} 

使用類像這樣的:

class Program 
{ 
    static void Main(string[] args) 
    { 
     IDictionary properties = new Dictionary<string, string>() { 
      { "prop1", "value1"}, { "prop2", "value2"} }; 
     var my = new MyClass(properties); 
     System.Console.WriteLine(my.prop1); // Doesn't work! 
    } 
} 

(注:我問了一下C++ here了類似的問題,原來同樣的問題,而是分裂,使每種語言更具體)

回答

1

你哈這是一個內置的支持。你應該從DynamicObject派生你的類並覆蓋它的TryGetMember/TrySetMember通過使用傳遞給構造函數的字典檢查屬性是否有效。

另一種選擇是僅使用ExpandoObject作爲一包屬性。但是,雖然動態語言具有某種程度的功能,但是您會丟失C#本機特徵,例如類型安全性,編譯時檢查和IDE代碼完成支持。

+0

非常好 - 這正是我一直在尋找的。非常感謝。 – 2014-11-02 11:01:23

+0

添加了我的示例使用DynamicObject進行記錄的答案。 – 2014-11-02 11:08:59

1

@galenus給了我接受的答案,但只是爲了記錄,我想我會添加更新爲使用DynamicObject的示例的代碼。

public class MyClass : DynamicObject 
{ 
    public IDictionary<string, object> Properties { get; private set; } 
    public MyClass(IDictionary<string, object> properties) 
    { 
     this.Properties = properties; 
    } 

    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     return Properties.TryGetValue(binder.Name, out result); 
    } 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     IDictionary<string, object> properties = new Dictionary<string, object>() { 
      { "prop1", "value1"}, { "prop2", "value2"} }; 
     dynamic my = new MyClass(properties); 
     System.Console.WriteLine(my.prop1); 
    } 
} 
+1

您可以使用Properties.TryGetValue代替檢查代碼中的Properties.Keys.Contains,然後提取值。它更簡潔。 – galenus 2014-11-02 11:16:51

+0

當然,@ galenus;我應該發現這一點。我已經更新了代碼以包含您的建議。 – 2014-11-02 11:42:45