Как реализовать выборочную видимость свойств в С#?
Можно ли сделать свойство класса видимым для публики, но может быть изменено только некоторыми конкретными классами?
например,
// 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(){}
}
Ребенок - это класс данных,
Родительский - это класс, который может изменять данные,
Cat - это класс, который может читать только данные.
Есть ли способ реализовать такой контроль доступа с помощью свойства в С#?
Ответы
Ответ 1
Вместо того, чтобы отображать внутреннее состояние класса Child, вы можете указать вместо этого метод:
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 { ... }
Ответ 2
Обычно это достигается с помощью отдельных сборок и InternalsVisibleToAttribute. Когда вы помечаете set
классами internal
, в текущей сборке будет доступ к нему. Используя этот атрибут, вы можете предоставить доступ к ним другим другим узлам. Помните, используя Reflection, он все равно будет доступен для редактирования.