2012-12-19 67 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将有权访问它时。通过使用该属性,可以让特定的其他程序集访问它。记住通过使用反射它仍然是可编辑的。