如何强制 class 实现构造函数?

How can I force a class to implements constructor?

我有一个接口IPopUp:

public interface IPopUp 
{
    bool IsCancelable {get;}
    void Show();
    void Close();
    Action MainAction{ get; }
    Action CancelAction{ get; }
}

我有几种实现方式:IfoPopUpErrorPopUpLoadingPopUp

我正在使用 PopUpManager 实例创建 PopUps 的实例

   public class PopUpManager
   {
      public void ShowPopUp<T>(string texto) where T:IPopUp 
      {
        ShowPopup (()=>(IPopUp)Activator.CreateInstance (typeof(T)));
      }

      public void ShowPopUp<T>(string texto,Action mainAction)where T:IPopUp 
      {
        ShowPopup (()=>(IPopUp)Activator.CreateInstance (typeof(T), mainAction));
      }

      public void ShowPopUp<T>(string texto,Action mainAction,Action cancelAction)where T:IPopUp 
     {
        ShowPopup (()=>(IPopUp)Activator.CreateInstance (typeof(T), mainAction, cancelAction));
     }

     private void ShowPopup(Func<IPopUp> factoryFunc)
     {
        if (PopUpShowed != null) {
            PopUpShowed.Close ();
        }
        IPopUp popUp = factoryFunc ();
        popUp.Show ();
     } 
}

我不知道如何强制 IPopUp 实现来实现我在 PopUpManager 中使用的 3 种构造函数。 Abstract class 将不起作用,因为它会强制构造函数... 有什么想法吗?

我最终重构了 class PopUpManager,所以它需要一个工厂委托来生成 PopUp。 很清楚,实例化 PopUps 的责任来自调用者,很有道理。

public void ShowPopUp(Func<IPopUp> factoryFuncPopUp)
{
    if (PopUpShowed != null) {
        PopUpShowed.Close ();
    }
    IPopUp popUp = factoryFuncPopUp();
    popUp.Show ();
}

无论如何,我很想知道哪种方法最适合强制 class 实现某些构造函数。

您已经为您的问题找到了很好的解决方案。这里有一些关于强制 class 实现某些构造函数的额外见解。

可以用接口来完成吗?

C# language specification 5.0 在第 13 章定义了什么是接口:

An interface defines a contract. A class or struct that implements an interface must adhere to its contract. An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.
Interfaces can contain methods, properties, events, and indexers. The interface itself does not provide implementations for the members that it defines. The interface merely specifies the members that must be supplied by classes or structs that implement the interface.

实例构造函数不是方法,不能成为接口的一部分。这个在13.2有明确提醒:

An interface cannot contain constants, fields, operators, instance constructors, destructors, or types, nor can an interface contain static members of any kind.

有很多理由证明这种语言设计选择是合理的,您可以在 SO 上找到一些额外的解释。另请注意,其他语言也有类似的限制。 Java 例如声明“接口不能直接实例化。

可以用摘要来完成吗class?

C# 语言规范在第 10.1.1.1 节中说明。那:

The abstract modifier is used to indicate that a class is incomplete and that it is intended to be used only as a base class. (...) An abstract class cannot be instantiated directly, and it is a compile-time error to use the new operator on an abstract class.

长话短说,如果您要在抽象 class 中定义三个不同的构造函数,派生的 classes 将不得不调用其中一个构造函数,但不会自行给出任何约束构造函数。请注意,此逻辑也适用于 C++ 或 Java.

摘要 class 的 link 及其派生的 class 就像 ShapeSquare 之间的 link , RectangleCircle 实现 Shape: 矩形的构造参数可能与圆形的构造参数有很大不同,因此 Shape 不能对其子项的构造函数施加约束。

可以用组合来完成吗?

您希望 PopupManager 实例化具有特定属性的 IPopUp。不幸的是,您不能以安全的方式直接实例化 IPopUpActivator.CreateInstance() 可能会触发异常)。

为了安全起见,您可以很好地强制 IPopUpMainActionCancelAction 要求 setter,并添加构造函数约束(例如 where T:IPopUp, new()) 以确保可以毫无意外地创建实例,并更改对象以满足需要。

但有些情况下需要在构建时提供参数。在这种情况下,您可以考虑使用 builder pattern 或您选择的工厂方法。请注意,在允许与静态成员接口的语言中,您甚至可以在 IPopUp 接口中强制使用三个静态工厂方法。

我遇到了类似的问题。就我而言,具有特定属性 [SpecialAttribute] 的 类 需要具有无参数构造函数。

我在每次构建后在我们的CI服务器上添加了一个测试运行,其中搜索具有该属性的类,然后调用Activator.CreateInstance .如果由于 MissingMethodExceptions 而失败,则测试 "fails" 并显示缺少无参数构造函数的 类。

这并不完美,因为代码仍然可以编译。但是带有明确消息的失败的自动化测试是向前迈出的重要一步。