How can I ensure that a class can call a method in another class, but not other classes can call this method?

I have two classes that I would like to store 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 can I guarantee that other classes are not allowed to call InformAddedToGrid?

I am trying to emulate ActionScript namespaces that can be used in a method instead of public, private, internal, etc. It does not protect the method exactly, but it forces an additional step to include the namespace until the method can be accessed. Is there an alternative approach to this in C #?

+6
source share
5 answers

Not that you do this, you should do what TGH offers, have an open interface for the GridItem, and have a gridItem embedded in the Grid (then there is a factory method on the Grid for creating the elements and using the partial Grid class for them in separate files) .

Since the friends method does not exist (you can make friends classes through InternalsVisibleToAttribute )

YOU CAN do it (but not ...)

 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... 
+1
source

If the GridItem itself can be hidden from the outside world, I would consider including GridItem inside the Grid as a nested class. This way it will not be visible outside the class

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

+5
source

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

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

Both of them are much slower to complete than a regular call.

I do not think there is a good answer. C # has no friends.

+1
source

IMHO, the answer is simple: access modifiers are there to remind the programmer how a public / private class should look. Through reflection, you can remove these barriers.

The use you make in the class is all at your fingertips: if your class is intended to be used in one place only, do it this way. If anything, if the class has a special use case, write it down - put it in an XML comment.

However, in this particular example, I would believe it, since GridItem does not add itself to the grid, it is not his task to notify about it (what if "I have not been added to the grid" ,?). I think InformAddedToGrid belongs somewhere in your Grid class as a private method, where there is the concept of adding an element ... assuming AddItem(GridItem) really works.

0
source

You can do this, as TGH suggested, with nested classes, except vice versa. Grid socket inside GridItem and make InformAddedToGrid private. Here I use a nested base class so that the public API remains the same. Note that none of your assembly can inherit from GridBase , because the constructor is internal.

 public class GridItem { public class GridBase { internal GridBase() { } public void AddItem(GridItem item) { item.InformAddedToGrid(); } } private void InformAddedToGrid() { Debug.Log("I've been added to the grid"); } } public class Grid : GridItem.GridBase { } 

Another option is to have GridItem explicitly implement the internal interface. Thus, none of your assembly can use the interface by name and therefore cannot call InformAddedToGrid .

 public class Grid { public void AddItem(GridItem item) { ((IGridInformer)item).InformAddedToGrid(); } } public class GridItem : IGridInformer { void IGridInformer.InformAddedToGrid() { Debug.Log("I've been added to the grid"); } } internal interface IGridInformer { void InformAddedToGrid(); } 
0
source

Source: https://habr.com/ru/post/952798/


All Articles