Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to implement selective property-visibility in c#?

Tags:

c#

Can we make a property of a class visible to public , but can only be modified by some specific classes?

for example,

// 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(){}
}

Child is a data class,
Parent is a class that can modify data,
Cat is a class that can only read data.

Is there any way to implement such access control using Property in C#?

like image 854
lowatt Avatar asked Dec 19 '12 05:12

lowatt


2 Answers

Rather than exposing the inner state of the Child class you could provide a method instead:

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);
  }
}

Then the cat can't beat your child:

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

If other people need to be able to beat the child, define an interface they can implement:

interface IChildBeater { }

Then have them implement it:

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

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

class Mother : IChildBeater { ... }

class Father : IChildBeater { ... }

class BullyFromDownTheStreet : IChildBeater { ... }
like image 117
Andrew Kennan Avatar answered Oct 21 '22 07:10

Andrew Kennan


This is usually achieved by using separate assemblies and the InternalsVisibleToAttribute. When you mark the set with internal classes within the current assembly will have access to it. By using that attribute, you can give specific other assemblies access to it. Remember by using Reflection it will still always be editable.

like image 40
Yuriy Faktorovich Avatar answered Oct 21 '22 09:10

Yuriy Faktorovich