【问题标题】:Performing in a various order several methods on the objects in collection以不同的顺序对集合中的对象执行几种方法
【发布时间】:2019-11-11 03:51:26
【问题描述】:

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

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

例如我已经定义了动作列表:

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...
        }
    }
}

请忽略任何不准确之处。

此解决方案有效。但是,“切换”指令非常大。我有几十个这样的动作。这可能不是最好的解决方案。

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

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

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

【问题讨论】:

  • 你考虑过将动作集合做成字典吗?
  • 你的想法是正确的,它会消除switch语句。将Action MethodToCallDelegate; 成员添加到MyAction 并将其设置为不同的方法,例如Method3。见Action

标签: c# collections foreach


【解决方案1】:

您可以将委托添加到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);
    }
}

诀窍是使用接受MyObjects 作为参数的Action&lt;MyObjects&gt; 委托。这允许您指定调用此对象上的方法的 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&lt;MyObjects&gt; 委托兼容的方法的特殊情况下,您可以将方法本身作为委托传递。您省略参数大括号表示您不想在此处调用它。

Action = Console.WriteLine

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

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

【讨论】:

    猜你喜欢
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-29
    • 2021-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多