我在下面有这个代码循环数据结构建立一个字典。
我将此代码重复多次,唯一的区别是字典的键
所以在下面的代码中恰好是:
task.Project + task.Name
这是字典的关键,但在其他情况下只是:
task.Project
或只是
task.Name
这是一个hte硬编码“Bucket”方法的例子。
我的目标是拥有一个通用的“Bucket”方法,我可以通过回调或某种方式传递函数来计算密钥。
这样做的最佳方式是什么?
private Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings)
{
Dictionary<string, TeamHours> dict = new Dictionary<string, TeamHours>();
foreach (var name in timebookings.Keys)
{
TimeBooking tb = timebookings[name];
Person p = tb.Person;
foreach (var booking in tb.WeeklyTimeBookings.Keys)
{
var item = tb.WeeklyTimeBookings[booking];
foreach (var task in item.TaskSlices)
{
if (dict.ContainsKey(task.Project + task.Name))
{
TeamHours th = dict[task.Project + task.Name];
th.Hours = th.Hours + task.Hours;
}
else
{
TeamHours th = new TeamHours();
th.Hours = task.Hours;
th.Project = task.Project;
th.Task = task.Name;
th.Workstream = tb.Person.OrganisationalUnitName;
dict[task.Project + task.Name] = th;
}
}
}
}
return dict;
}
答案 0 :(得分:2)
嗯,你自己大多回答了这个问题。将委托传递给方法或继承不同的实现,并通过实现抽象方法进行专门化。另一种选择是将密钥构建算法分离为接口,这样可以最大程度地分离关注点,但是对于简单的场景来说,开销可能太大了。
private Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings, Func<string, Task> getTaskKey)
{
…
dict[getTaskKey(task)] = th;
…
}
非常适合在高度本地化的场景中使用(即实现和使用私有的单个类),只需几个简单的关键构建表达式。
class abstract BucketAlgorithm
{
protected abstract string GetTaskKey(Task task);
public Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings)
{
…
dict[GetTaskKey(task)] = th;
…
}
}
class SpecificBucketAlgorithm : BucketAlgorithm
{
protected override string GetTaskKey(Task task) { … }
}
适合在中等范围内使用,例如一个程序集,不需要更好地分离关注点(接口与实现),或者需要几个非平凡的关键构建算法。
interface ITaskKeyGenerator
{
string GetTaskKey(Task task);
}
class BucketAlgorithm
{
public BucketAlgorithm(ITaskKeyGenerator taskKeyGenerator)
{
this.taskKeyGenerator = taskKeyGenerator;
}
private ITaskKeyGenerator taskKeyGenerator;
public Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings)
{
…
dict[taskKeyGenerator.GetTaskKey(task)] = th;
…
}
}
适用于需要彻底分离关注点或可能存在多个复杂的密钥构建算法的情况,或者甚至是由API用户从“外部”提供的情况。