【问题标题】:Ensuring class A can only be created by class B确保 A 类只能由 B 类创建
【发布时间】:2013-01-24 16:22:15
【问题描述】:

我已经阅读了一些关于 SO(和其他地方)关于这个主题的讨论,但无法收集到明确的答案。

我想确保给定的类 A 只能由特定的类 B 创建。在 C++ 中,我将 A 的构造函数设为私有,并将 B 指定为友元。现在只有 B 可以创建 A。

如果确实有的话,在 C# 中执行此操作的惯用方式是什么?

【问题讨论】:

    标签: c# constructor factory


    【解决方案1】:

    您可以为此使用 private 内部类。

    但是,这用途有限。

    class B
    {
      private class A
      {
      }
    }
    

    【讨论】:

    • 如果私有类 A 实现了一个公共接口,那么您可以将该接口暴露给外界。
    • A 的公共内部类呢?即A类{公共B类{A MakeA(){....}}私有A(){}; }
    • @TomDavies - 这样的内部类可以被其他类实例化,它只是外部类的inside。请参阅此相关的 SO 答案:stackoverflow.com/a/337143/1583
    【解决方案2】:

    您不能在 C# 中使用 C++ 风格的方法。

    我之前也遇到过这个问题,我通常通过将A类设为abstract(需要继承)和构造函数protected(只有继承自该类的类才能调用构造函数)来解决。

    然后我在 B 类中创建一个private 类(称为“_A”之类的东西)并从 A 继承。(_A 中没有其他代码。)_A 定义了一个公共的构造函数 - 因此对 B 可见(并且仅限 B,因为 _A 是私有的)。

    在 B 中,您可以创建 _A 的实例并将它们作为 A 返回(通过polymorphism)。

    对于公共接口,我更喜欢这种方法,因为如果在其中实现 A 类,我的 B 类代码文件最终会很大。不过,这只是我的偏好 - 其他人可能有不同的意见。

    abstract class A
    {
    
        protected A()
        {
        }
    
        /* implementation details... */
    
    }
    
    public class B
    {
    
        public A GetInstance()
        {
            return new _A();
        }
    
        private class _A : A
        {
    
            public _A()
            {
            }
    
        }
    
    }
    

    【讨论】:

    • 最后一个构造函数不应该是public _A吗?
    • @spender - 谢谢,已修复。尚未实际编译此代码 - 仅用于演示。 :)
    【解决方案3】:

    我假设外部代码需要引用A,但应该不能创建实例。

    没有简单的方法可以实现这一点。如果您将A 的构造函数设为internal,那么只有与A 在同一程序集中的代码才能构造它(不使用反射)。

    可以创建一个StackTrace 的实例并检查索引1 处的帧,看看它是否来自B 的方法,但这可能会导致性能问题,而且很友好一个黑客。

    【讨论】:

      【解决方案4】:

      这是可行的,但以令人讨厌的方式。可以说比 C++ 中的“朋友”概念更令人讨厌。

      您可以声明私有构造函数和静态工厂方法,您将只允许特定类型调用此方法(通过检查 StackFrame)。

      public class Foo
      {
        private Foo() { }
      
        public static Foo Create()
        {
          if(GetCallingType() != typeof(Bar))
          {
            throw new Exception("Only Bar can create Foo");
          }
          return new Foo();
        }
      
        private static Type GetCallingType()
        {
          return new StackFrame(2, false).GetMethod().DeclaringType;
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-11-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-02
        • 1970-01-01
        相关资源
        最近更新 更多