2012-12-19 107 views
10

我們可以讓一個類的屬性公開,但只能被某些特定的類修改嗎?如何在c#中實現選擇性屬性可見性?

例如,

// this is the property holder 
public class Child 
{ 
    public bool IsBeaten { get; set;} 
} 

// this is the modifier which can set the property of Child instance 
public class Father 
{ 
    public void BeatChild(Child c) 
    { 
     c.IsBeaten = true; // should be no exception 
    } 
} 

// this is the observer which can get the property but cannot set. 
public class Cat 
{ 
    // I want this method always return false. 
    public bool TryBeatChild(Child c) 
    { 
     try 
     { 
      c.IsBeaten = true; 
      return true; 
     } 
     catch (Exception) 
     { 
      return false; 
     } 
    } 

    // shoud be ok 
    public void WatchChild(Child c) 
    { 
     if(c.IsBeaten) 
     { 
      this.Laugh(); 
     } 
    } 

    private void Laugh(){} 
} 

兒童是一個數據類,
家長是一類可以修改數據,
是一個類只能讀取數據。

有沒有什麼辦法可以在C#中使用Property實現這種訪問控制?

回答

4

而不是暴露兒童類的內部狀態,你可以提供替代的方法:

class Child { 
    public bool IsBeaten { get; private set; } 

    public void Beat(Father beater) { 
    IsBeaten = true; 
    } 
} 

class Father { 
    public void BeatChild(Child child) { 
    child.Beat(this); 
    } 
} 

於是貓不能擊敗你的孩子:

class Cat { 
    public void BeatChild(Child child) { 
    child.Beat(this); // Does not compile! 
    } 
} 

如果其他人需要能夠擊敗孩子,定義他們可以實現一個接口:

interface IChildBeater { } 

然後讓他們實現它:

class Child { 
    public bool IsBeaten { get; private set; } 

    public void Beat(IChildBeater beater) { 
    IsBeaten = true; 
    } 
} 

class Mother : IChildBeater { ... } 

class Father : IChildBeater { ... } 

class BullyFromDownTheStreet : IChildBeater { ... } 
+0

thx。但如果我們無法定義或更改_Beater_,該怎麼辦?即_Child_代碼是客戶端代碼,而_Beater_可能是一個第三方包,它實現了一些功能,如序列化,後來可以被另一個自由職業取代? – lowatt

+0

在這種情況下,你可能做的並不多。如果Beater的作者定義了它與Child之間的相互作用,那麼你可能只需要相信第三方會做正確的事情。這是一個教育和文檔問題,而不是代碼中可以解決的問題。 –

2

這通常通過使用單獨的組件和InternalsVisibleToAttribute來實現。當您在當前程序集內使用類標記set將有權訪問它時。通過使用該屬性,可以讓特定的其他程序集訪問它。記住通過使用反射它仍然是可編輯的。