如何将委托列表作为参数传递(以 "pretty" 方式)

How to pass a List of delegates as a parameter (in a "pretty" way)

我有一个变得太大的构造函数(12 个参数)。 所有这些参数要么是 Actions (Action, Action) 要么是通用委托(我有大约 8 个)。

如何传递委托列表,从而以一种仍然可读的方式减少构造函数的参数数量?我想实现这样的目标:

// Controller //
var methods = new List<StrategyDelegate>()
{
    model.OpenWindowMethod,
    model.CloseWindowMethod
};
View(methods);

// View //
public delegate void StrategyDelegate();
private StrategyDelegate _openWindow;
private StrategyDelegate _closeWindow;

View(List<StrategyDelegate> methodsToCall)
{
    _openWindow = methodsToCall.Find("model.OpenWindowMethod"); ???
    _closeWindow = methodsToCall[1]; ???
}

但是我不喜欢这两种方法,因为其中一种使用字符串,而另一种我必须知道列表的顺序,如果我删除其中一种方法,我可能必须重新排序整个方法东西。

有什么想法吗?

创建一个新的 Class,它有一大堆设置方法,用于您要从 Controller 传递给 View 的不同委托;基本类型的简单示例:

public class ViewConfiguration {
    public int a;
    public int b;
    public string c;
    public bool d;

    public ViewConfiguration setA(int newA) {
        // setB, setC, and setD will follow a similar structure
        a = newA;
        return this;
    }
}

然后Controller可以进行如下配置:

var config = new ViewConfiguration();
// you can do any combination/order of these
config.setA(2).setB(4).setC("hello").setD(true);

然后你可以将config传递给View,View可以简单地做config.a。您可能应该这样做,以便只有 public 具有属性(隐藏设置方法后面的直接设置字段),但这是一个普遍的想法。

将许多委托作为构造函数的参数传递听起来不是最佳做法。将它们作为 List<delegate> 传递可能对我来说更糟。它带来了一些额外的风险。但这应该不是问题。

如果您尝试将 class 作为参数传递会怎样:

public class MyActions
{
    public StrategyDelegate OpenWindow { get; set; }
    public StrategyDelegate CloseWindow { get; set; }
}

但这意味着您可以随时更改方法(此处声明为属性)。您可以将其更改为一个结构,这样它将创建一个副本,因此在将它们传递给构造函数后无法更改操作。


如果在 运行:

期间不更改委托,我想我会选择继承

我会创建一个摘要 class:

public abstract class MyBaseClass
{
    public abstract void OpenWindow();
    public abstract void CloseWindow();  // <-- at least pass a object sender?
}

public class MyClass : MyBaseClass
{
    public override void OpenWindow()
    { 
        // you code:
    }

    public override void CloseWindow()
    {
        // you code:
    }
}

public class ViewConfiguration 
{
    public MyBaseClass _myBaseClass;

    public ViewConfiguration(MyBaseClass myBaseClass)
    {
        _myBaseClass = myBaseClass;
    }


    public void CloseWindow()
    {
        _myBaseClass?.CloseWindow();
    }
}