Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I ensure a Class can call a method on another Class, but not other Classes can call that method?

Tags:

c#

I have two classes that I'd like to keep in separate files.

namespace GridSystem
{
    public class Grid
    {
        public void AddItem(GridItem item)
        {
            item.InformAddedToGrid();
        }
    }
}

namespace GridSystem
{
    public class GridItem
    {
        public void InformAddedToGrid()
        {
            Debug.Log("I've been added to the grid");
        }
    }
}

How do I ensure no other classes are allowed to call InformAddedToGrid?

I'm trying to emulate Actionscript namespaces, which can be used on a method, in place of public, private, internal, etc. It doesn't exactly protect the method, but forces an extra step of including the namespace before the method can be accessed. Is there an alternative approach to this in C#?

like image 256
Jimmie Tyrrell Avatar asked Aug 30 '13 03:08

Jimmie Tyrrell


3 Answers

If GridItem itself can be hidden from the outside world as well I would consider putting GridItem inside Grid as a nested class. That way it won't be visible outside of the class

http://www.codeproject.com/Articles/20628/A-Tutorial-on-Nested-Classes-in-C

like image 105
TGH Avatar answered Oct 05 '22 22:10

TGH


Not that you should do this, you should do what TGH suggests, have a public interface for GridItem, and have gridItem nested in Grid (then have a factory method on Grid to create Items and use partial Grid class to have them in separate files).

Because there isn't a way of having friend methods ( you can do friend classes through InternalsVisibleToAttribute )

You COULD do this ( but don't... )

public partial class Grid
{
   public void AddItem(GridItem item)
   {
      item.InformAddedToGrid();
   }
}        

public class GridItem
{
   public void InformAddedToGrid()
   {                
      if (new StackTrace().GetFrame(1).GetMethod().DeclaringType != 
                   typeof(Grid)) throw new Exception("Tantrum!");
      Console.WriteLine("Grid called in...");

   }
}

then

 var g = new Grid();
 g.AddItem(new GridItem()); // works
 new GridItem().InformAddedToGrid(); // throws a tantrum...
like image 43
Keith Nicholas Avatar answered Oct 06 '22 00:10

Keith Nicholas


A really ugly answer would be to make it private and use reflection.

Another ugly answer would be to make it throw an exception if the caller is wrong.

Both of these are much slower to execute than a normal call also.

I don't think there's a good answer. C# doesn't have friends.

like image 43
Loren Pechtel Avatar answered Oct 06 '22 00:10

Loren Pechtel