我的应用程序中的用户可以决定哪些活动以及要按什么顺序进行对象的收集。该订单是在所有对象的开头(一次(设置的。
用户选择的方法应由应用程序以正确的顺序执行。
例如,我定义了动作列表:
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}
我不知道如何实现它(或类似的解决方案(。我希望我的代码在以后的版本中保持透明和简单。
您可以将委托给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<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
。(请注意,我假设您在MyObjects
中已覆盖ToString
,否则只会打印类型名称。(
另请参见:lambda表达式(C#编程指南(