以各种顺序对集合中的对象执行几种方法

时间:2019-06-29 17:39:52

标签: c# collections foreach

我的应用程序中的用户可以决定要执行哪些活动以及以什么顺序执行对象的收集。顺序是在所有对象的开头(一次)设置的。

用户选择的方法应由应用程序以正确的顺序执行。

例如,我定义了动作列表:

this.ActionsList = new List<MyAction>
{
    new MyAction {Id = "123", Order = 1, Text = "Method 5", IsActive = true},
    new MyAction {Id = "abc", Order = 5, Text = "Method 1", IsActive = false},
    new MyAction {Id = "def", Order = 3, Text = "Method 3", IsActive = true}
};

我也有一些对象:

var myObjects = new List<MyObjects>();

现在,对于集合中的每个对象,程序必须调用与已激活操作关联的方法。定义的操作定义了将调用哪个方法。

foreach (var o in myObjects){

    var actions = ActionsList.Where(x => x.IsActive).OrderBy(x => x.Order);

    foreach (var a in ActionsList){
        switch(a.Id){
            case "123":
                o.Method5();
                break;
            case "abc":
                o.Method1();
                break;
            // etc...
        }
    }
}

请忽略任何不正确之处。

此解决方案有效。但是,“ switch”指令非常大。我有许多这样的动作。这可能不是最佳解决方案。

我认为最好的解决方案是为每个对象“ MyAction”指示适当的方法(代理):

new MyAction {Id = "def", Order = 3, Text = "Method 3", IsActive = true, 
MethodToCallDelegate = Method3}

我不知道如何实现(或类似的解决方案)。 我希望我的代码在将来的版本中透明且简单。

1 个答案:

答案 0 :(得分:2)

您可以将委托添加到MyAction

public Action<MyObjects> Action { get; set; }

然后可以像这样初始化动作列表:

this.ActionsList = new List<MyAction> {
   new MyAction { Order = 1, Text = "Method 5", Action = o => o.Method5(), IsActive = true },
   new MyAction { Order = 5, Text = "Method 1", Action = o => o.Method1(), IsActive = false },
   new MyAction { Order = 3, Text = "Method 3", Action = o => o.Method3(), IsActive = true }
};

动作可以这样应用

var orderedActions = ActionsList
    .Where(a => a.IsActive)
    .OrderBy(a => a.Order)
    .ToList();
foreach (MyObjects o in myObjects) {
    foreach (MyAction action in orderedActions) {
        action.Action(o);
    }
}

诀窍是使用Action<MyObjects>委托接受MyObjects作为参数。这使您可以指定一个lambda表达式,该表达式在此对象上调用一个方法。如果需要,您甚至可以将参数传递给此类方法:

Action = o => o.StringMethod1("Hello")
Action = o => o.StringMethod2("Hello", "World")

或做完全不同的事情

Action = o => o.Text = "okay"
Action = o => Console.WriteLine(o)
Action = o => { o.Text = "statement lambda"; Console.WriteLine(o); }

该委托保持不变,因为它始终具有一个MyObjects参数。

在特殊情况下,如果您要调用与Action<MyObjects>委托兼容的方法,则可以将方法本身作为委托传递。您省略了参数括号以表示您不想在此处调用它。

Action = Console.WriteLine

这将与o => Console.WriteLine(o)具有相同的效果,但是效率更高。它不会调用由lambda表达式创建的委托,该委托又依次调用Console.WriteLine,而是直接调用Console.WriteLine。 (请注意,我假设您已经在ToString中覆盖了MyObjects,否则只会打印类型名称。)

另请参阅:Lambda expressions (C# Programming Guide)