【问题标题】:C#/.Net enforcing (or just 'hint to fellow developers') that a class method is only supposed to be called from another specific class?C#/.Net 强制(或只是“提示其他开发人员”)一个类方法只能从另一个特定类调用?
【发布时间】:2011-05-08 14:04:05
【问题描述】:

我目前正在做一些内部特定领域的库开发,顺便说一下,我试图模拟的东西很好地模仿了“类”和“对象”的关系。所以我的 C# 类 MyClass 的对象应该有点像我的 C# 类 MyObject 的对象的 域特定类,他们扮演 对象或实例。现在我希望 MyObject 中的代码能够访问 MyClass 的方法,项目中的其他类/代码不应访问这些方法。除了记录它以希望我的开发人员同事尊重这一点之外,任何关于如何执行此操作的想法。

我希望我的问题足够清楚,否则请告诉我。

最好的问候!

【问题讨论】:

  • 什么?对我来说(我敢打赌其他几个)“class”==“object”。
  • 我发现您的问题令人困惑。对象是类的实例,我不确定您是否有两个类,一个称为 MyObject,一个称为 MyClass,或者您是否有一个类和一个对象?
  • @Will:我建议你把 MyClassas 读成 MyCategory
  • 是的,我可能在这里选择了令人困惑的措辞,但我想表达我们通常在类和此类的对象之间存在的相同类型的关系,但在运行时的对象之间。这是否使它更清晰甚至更糟?
  • @S.C.我认为 Henk 的回答将最好地解决您的问题。您只需要确保 MyClass 和 MyObject 在同一个程序集中,并且其中没有其他东西可以访问 MyObject 的内部方法。

标签: c# .net


【解决方案1】:

您始终可以将MyClassMyObject 拆分到另一个项目中,并将MyClass 和/或MyObject 定义为internal 类。这样,它只能被该程序集中的其他对象访问。

见:http://msdn.microsoft.com/en-us/library/7c5ka91b(VS.80).aspx

【讨论】:

  • 所以我应该为这两个类创建一个程序集?我认为这似乎有点“繁重”。不过还是谢谢你的建议。
  • 也许,但这取决于您的应用程序;如果这些类中最终有很多特定于域的逻辑,那么一个新项目可能是将这些逻辑与应用程序的其余部分分开的好方法。
【解决方案2】:

这里的标准方法是声明成员 internal 并确保 MyClass 和 MyObject 是同一程序集的一部分。该程序集应该几乎没有其他内容。

附加:这是为此目的而设计的工具。其他语言有其他方法来微调可访问性(C++:friend),但在 .NET 中选择了更简单的模型。

而且您不必如此严格地接受“没有别的”,这两个类可以与其他相关类共享一个程序集。然后,您必须在该库中手动验证禁止访问规则。

【讨论】:

  • 所以我应该只为 2 个类创建一个程序集?
【解决方案3】:

我建议private nested class。这样,即使您的开发人员在同一个命名空间中编写代码,他们也永远无法访问该类。

一旦类声明完全包含在另一个类声明中,该类就被认为是嵌套的,只能通过包含的类进行访问。

【讨论】:

  • 我假设他希望两个类上的某些方法可以公开访问,但他希望其中一个类上的某些方法只能由另一个类访问,而不是公开访问。此解决方案使整个第二类无法公开访问。
  • 公平的建议,但我需要从“工厂”实例化这两种对象,这在运行时会有所不同。我不确定嵌套类会处理这个问题吗?
【解决方案4】:

也许您的 MyObject 应该从 MyClass 继承并将 MyClas 中的方法声明为受保护。

【讨论】:

  • 好吧,我不认为我的“实例”是一个“类”,所以这似乎是错误的。
  • 听起来 MyObject 模拟了 MyClass 的一个实例。
【解决方案5】:

如果您不希望您的消费者调用某些特定于实现的方法,您可以尝试抽象为接口或抽象基类。这样,消费者将只会“看到”您希望他们看到的属性和方法。

您不必使用继承来提供共享功能,也不必依赖成员可访问性来防止其他人使用您不想公开的方法。

例如:

public interface IDomainSpecific
{
   void DoStuff();
} 

public interface IDomainService
{
   void HelpMeDoStuff();
}

public class DomainObject1 : IDomainSpecific
{
  private readonly IDomainService _service;

  public DomainObject1( IDomainService service )
  {
    _service = service;
  }

  public DoStuff()
  {
    // Do domain specific stuff here 
    // and use the service to help
    _service.HelpMeDoStuff();
  }
}

这使用经典的构造函数注入,并且当您已经在应用程序中使用依赖注入时效果最佳,尽管它也可以与工厂完美配合。

关键是要保持责任清晰。任何人都不可能调用他们不应该调用的任何东西,因为“DomainObject”永远不知道实现共享服务的具体类型。共享服务也不暴露在域对象上。额外的好处是可测试性以及将服务与另一个实现交换的可能性,而无需接触 DomainObject。

【讨论】:

  • 对,我喜欢这个声音。可以举个例子吗?
  • 抽象不同于可访问性。 S.C. 在接口和抽象基类方面仍然会遇到同样的问题。
  • @Dave White:他必须隐藏构造函数并创建工厂方法来创建实例,但这没什么大不了的。至少它可以作为“给其他开发者的提示”。
  • @TMN - 当然。完全可行。但是您已经在原始答案中添加了“可访问性”概念,它本身是不完整的,并且不能解决 OP 的问题。
  • 我解释问题的方式有两个合同;您的“实例”的通用(公共?)接口以及“实例”与其“类”之间的合同。后者是可以注入“实例”的内部依赖项。这将使内部结构与公共内容完全分开。无论每个类驻留在哪个程序集中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-08
  • 1970-01-01
  • 2013-01-04
  • 1970-01-01
  • 2013-05-10
相关资源
最近更新 更多