【问题标题】:Make classes accessible only by static object使类只能由静态对象访问
【发布时间】:2015-03-27 12:44:50
【问题描述】:

我正在.Net 中创建一个库

我有一个名为 DataManager 的静态类。

public static class NewDataManager
{
    public static Soccer Soccer { get; private set; }

    static NewDataManager()
    {
         Soccer =  new Classes.Soccer.Soccer();
    }
}

足球课是这样的:

public class Soccer
{
    public static Mapping.Mapping Mappings { get; private set; }

    public Soccer()
    {
        Mappings = new Mapping.Mapping();
    }
}

而 Mapping 类只是另一个公共空类。

当我将此项目用作另一个项目中的引用时,我可以像这样访问我的对象

NewDataManager.Soccer.Mappings

没关系,这就是我想要的。问题是,我可以初始化引用项目中的所有类,例如

var s = new Soccer();
var m = new Mapping();

我希望这些类只能通过我的NewDataManager 类访问,使用我的库的项目不应该能够初始化类。

我该如何限制呢?

【问题讨论】:

  • newdatamanager 的所有其他类 - 将它们设置为内部/私有而不是公共
  • Soccer 本身不是静态的有什么原因吗?还是Mappings
  • @VisualBean internal/private 根本无法在他的项目中访问它——即使他想通过 NewDataManager 访问它
  • @MattBurland 没有任何理由。我就是这样创建它们的。

标签: c# .net static-classes


【解决方案1】:

要防止另一个程序集实例化一个类,请将其构造函数设为internal:

public class Soccer
{
    public static Mapping.Mapping Mappings { get; private set; }

    internal Soccer()  //  <-- instead of 'public'
    {
        Mappings = new Mapping.Mapping();
    }
}

public class Mapping
{
    internal Mapping()
    {
    }
}

(顺便说一句,您的命名空间似乎名为 SoccerMappingDon't do this.

【讨论】:

    【解决方案2】:

    这是有效实现您想要的目标的一种方法。将Soccer 嵌套在NewDataManager 中,然后您可以执行以下操作:

    public static class NewDataManager
    {
        public static ISoccer SoccerInstance { get; private set; }
    
        static NewDataManager()
        {
             SoccerInstance =  new Soccer();
        }
    
        private class Soccer : ISoccer
        {
    
            public Soccer()
            {
            }
        }
    }
    
    public interface ISoccer {}
    

    创建嵌套类private 意味着它不能在NewDataManger 之外访问,但您仍然可以通过实现公共接口来公开它。当然,您可以添加需要向接口公开的任何属性,以便调用代码可以使用它们。我通过省略 Mapping 属性来简化我的示例。

    现在,如果您不想嵌套类,则不必这样做。您可以将它们标记为internal,它们对其他程序集不可见,但它们将在同一个程序集中可见。这意味着除NewDataManger 之外的同一程序集中的类将能够看到它们(并创建新实例),但其他程序集则不能。这对你来说可能就足够了。

    【讨论】:

    • 嵌套类...很好的解决方案:)
    【解决方案3】:

    因为这些类是公开的 - 您可以从“任何地方”访问它们

    公开

    The type or member can be accessed by any other code in the same assembly or another assembly that references it.
    

    私人

    The type or member can be accessed only by code in the same class or struct.
    

    受保护

    The type or member can be accessed only by code in the same class or struct, or in a class that is derived from that class.
    

    内部

    The type or member can be accessed by any code in the same assembly, but not from another assembly.
    

    MSDN article about access modifiers

    【讨论】:

    • 这解释了问题,但并没有真正回答如何实现 OP 试图做的问题。
    • 已更新答案 -> 正在进行测试
    • 您不能创建类internal,然后将其公开为public 属性。
    【解决方案4】:

    让我扩展 VisualBean 的解决方案: 正如他所描述的,类有其可访问性特征,就像函数一样——公共的、私有的、受保护的、内部的等等。

    所以第一个解决方案只是在同一个程序集中定义 NewDataManager 和 Soccer 类,并将 Soccer 内部和 NewDataManager 公开,如下所示:

    public class NewDataManager{/*Your code goes here*/}
    internal class Soccer{/*Your code goes here, 2*/}
    

    在另一个文件中,你可以把剩下的代码放进去。

    不过,有一些替代方案可能更合适(取决于您的情况)。如果一个类只能被另一个类的单一类型访问,恕我直言,它应该与该类相关。为了在类中包含类,您有两种方法:

    要么使构造函数受保护,要么使类继承另一个类(如果对象相互扩展,这是一个很好的解决方案), 即

    class Soccer{protected Soccer(){} /*Rest of the code goes here*/}
    class NewDataManager:Soccer{// NewDataManagerStuff }
    

    或者将生成设置为需要发送者是您正在寻找的类的事件,这可能会稍微复杂一些。

    祝你好运,希望对你有所帮助。 :)

    【讨论】:

    • NewDataManager 将拥有更多类似 Soccer 的类,所以我无法从 Soccer 派生它。
    【解决方案5】:

    只需像这样将Mapping 类插入NewDataManager

    public static partial class NewDataManager 
    {
        // NewDataManager class code
    }
    
    public partial class NewDataManager
    {
        public static class Mapping
        {
            // Mapping class code
        }
    }
    

    public static class NewDataManager 
    {
        // NewDataManager class code
    
        public static class Mapping
        {
            //Mapping class code
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-07
      • 2018-04-07
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      • 2020-01-12
      相关资源
      最近更新 更多