繁体   English   中英

如何确保类可以在另一个类上调用方法,但其他类不能调用该方法?

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

我有两个类,我想保留在单独的文件中。

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

如何确保不允许其他类调用InformAddedToGrid?

我正在尝试模拟Actionscript命名空间,它可以在方法上使用,代替公共,私有,内部等。它并不完全保护方法,但强制在方法之前包含命名空间的额外步骤被访问。 在C#中有替代方法吗?

如果GridItem本身也可以从外部世界隐藏,我会考虑将GridItem作为嵌套类放在Grid中。 这样,它就不会在课堂外看到

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

一个非常难看的答案是将其设为私有并使用反射。

另一个丑陋的答案是如果调用者出错则使其抛出异常。

这两个执行都比正常调用慢得多。

我认为没有一个好的答案。 C#没有朋友。

不是你应该这样做,你应该做TGH建议的,有一个GridItem的公共接口,并且gridItem嵌套在Grid中(然后在Grid上有一个工厂方法来创建Items并使用部分Grid类将它们放在单独的文件中) 。

因为没有办法有朋友方法(你可以通过InternalsVisibleToAttribute做朋友课)

可以这样做(但不...)

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...");

   }
}

然后

 var g = new Grid();
 g.AddItem(new GridItem()); // works
 new GridItem().InformAddedToGrid(); // throws a tantrum...

恕我直言答案很简单:访问修饰符只是为了提醒程序员一个类应该是公共/私有的意图 通过反思你可以解除这些障碍。

你犯了一个类的用法是所有在你的手中:如果你的类是只在一个地方使用,使它如此。 如果有的话,如果一个类有一种特殊的使用方式,请记录它 - 将它放在XML注释中。

也就是说,在这个具体的例子中我会相信,因为GridItem不会将自己添加到网格中,所以通知它不是它的工作(如果“ 我没有被添加到网格中,那该怎么办?)。 我认为InformAddedToGrid属于你的Grid类中的某个private方法,其中有一个添加项的概念......假设这是AddItem(GridItem)真正做的事情。

你可以像TGH建议的那样,使用嵌套类,除了相反的方法。 GridItem嵌套Grid并将InformAddedToGrid私有。 这里我使用嵌套的基类,因此公共API可以保持不变。 请注意,程序集外部没有人可以从GridBase继承,因为构造函数是内部的。

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 { }

另一个选择是让GridItem显式实现内部接口。 这样,程序集外部没有人可以按名称使用接口,因此无法调用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();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM