在 C# 中访问其成员函数时如何防止调用一个 class 的构造函数?

How to prevent calling constructor of one class while having access to its member functions in C#?

我有一个classA和一个classAStore。我的要求是防止所有其他方法初始化 class A 的实例,它们应该从 AStore 获取实例。另外,我还需要从实例中访问A的成员函数。

工厂模式不适用于此问题,因为 A 的构造函数仍然是 public。理想情况下,在访问其成员函数时调用 class A 的构造函数时应该抛出编译错误。

我可以获得此问题的 C# 解决方案吗?

为了限制其他人创建 class A 的实例,您可以使用私有构造函数和静态工厂方法来获取 class 的实例。

public class A
{
  private A(){}

  public static A GetInstance()
  {
    return new A();
  }

  public void MemberFunctionOfA()
  {
  // blah blah...
  }
}

要强制仅通过 Astore 创建 A 的实例,您可以使用受保护的修饰符并从 A 派生 AStore。这样,只有 AStore 才能访问其受保护的成员,如 'constructor' 或 'factory method':

public class Astore : A
{
    public A GetInstanceOfA()
    {
        return base.GetInstance();
    }
}

public class A
{
    protected A() { }

    protected A GetInstance()
    {
        return new A();
    }

    public void MemberFunctionOfA()
    {
        // blah blah...
    }
}

//Usage
public class ConsumerClass
{
    public void Test()
    {
        var a = new A(); // Compile error
        a = new Astore().GetInstanceOfA();
        a.MemberFunctionOfA();
    }
}

但是另一个 class 说 'UnWantedStore' 仍然有可能派生自 A 并提供 A 的实例。

你也可以用反射来做到这一点:

public class ClassA
{
    // The constructor(s) have to be private
    private ClassA() { }

    // Whatever other code you want
}

public class ClassB
{
    public static ClassA GetClassAInstance()
    {
        // Use reflection to get the private default constructor
        ConstructorInfo constructor = typeof(ClassA).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null);
        ClassA instance = constructor.Invoke(new object[] { }) as ClassA;

        return instance;
    }
}

您可以找到有关 GetConstructor 方法的更多信息 here

另一种方法是将 AStoreA classes 移动到专用项目,并将 A class 的构造函数内部化。

// Project A
namespace ProjectA
{
    public class A
    {
        public int PropertyOne { get; set; }
        public string PropertyTwo { get; set; }

        internal A() {}            
    }

    public class AStore
    {
        public A CreateA()
        {
            //internal constructor can be used
            return A();
        }
    }
}

// Project ConsumerOfA
namespace ConsumerOfA
{
    public static void UseA()
    {
        var store = new AStore();
        var instanceOfA = store.CreateA();

        // have access to the A's public members
    }
}

通过这种方法,您将获得您想要实现的完美封装。

摘要 class 来拯救!

的确,还有另一种可能的方法!我从未使用过它,但它可能适用于您的场景。请参阅以下代码示例:

public abstract class A 
{
    public string Text { get; set; }

    public string SayHello() => "hello world!";
}

public class AStore
{
     private class AInternal : A {}

     public void DoStuff()
     {
         A a = new AInternal();
         a.Text = "whatever";
         string helloText = a.SayHello();
     }
}

让我们解释一下方法:

  • Class A 是抽象的,因此无法实例化。
  • Class AStore 实现了一个名为 AInternalprivate 嵌套 class,它继承了 AAStore 成员能够实例化A。由于 AInternal 是私有的,除 AStore 之外没有其他 class 可以实例化 AInternal!
  • Class AStore 可以访问 public A 成员,因为 AInternal 继承了 A!