受到Wery Nguyen的启发,我对我的类进行了全面的通用重构。我最初发布的代码片段并不是整个问题,但我认为它可以解释我的意思。我应该直接发布整个代码。
我得出了这个:
#region Private methods
static IEnumerable<TrackInfo> ProcessItems<T>(IEnumerable<T> items, Func<DataContext, IEnumerable<T>, IEnumerable<TrackInfo>> func)
{
using (var dataContext = new DataContext())
{
foreach (var item in func(dataContext, items))
{
yield return item;
}
dataContext.SubmitChanges();
}
}
static IEnumerable<TrackInfo> ProcessItems<T>(DataContext dataContext, IEnumerable<T> items, Func<DataContext, T, TrackInfo> func)
{
return items.Select(t => func(dataContext, t));
}
TrackInfo ProcessItem<T>(DataContext dataContext, T item, Action<TrackInfo> action)
{
if (typeof(T) == typeof(string))
{
return ProcessItem(dataContext, this[item as string], action);
}
if (typeof(T) == typeof(TrackInfo))
{
var track = item as TrackInfo;
action(track);
return track;
}
throw new ArgumentException("The type must be string or TrackInfo");
}
#endregion
#region Public methods
public IEnumerable<TrackInfo> Add<T>(IEnumerable<T> items)
{
return ProcessItems(items, Add);
}
public IEnumerable<TrackInfo> Add<T>(DataContext dataContext, IEnumerable<T> items)
{
return ProcessItems(dataContext, items, Add);
}
public TrackInfo Add<T>(DataContext dataContext, T item)
{
return ProcessItem(dataContext, item,
i =>
{
dataContext.TrackInfos.InsertOnSubmit(i);
Add(i);
});
}
public IEnumerable<TrackInfo> Delete<T>(IEnumerable<T> items)
{
return ProcessItems(items, Delete);
}
public IEnumerable<TrackInfo> Delete<T>(DataContext dataContext, IEnumerable<T> items)
{
return ProcessItems(dataContext, items, Delete);
}
public TrackInfo Delete<T>(DataContext dataContext, T item)
{
return ProcessItem(dataContext, item,
i =>
{
dataContext.TrackInfos.Attach(i);
dataContext.TrackInfos.DeleteOnSubmit(i);
Remove(i);
});
}
代码中没有冗余,但我不确定可读性是否很好。尽管如此,这是一次有趣的学习经历。
简单解释一下。有两个通用的ProcessItems和一个ProcessItem。每个都是连续重载Add和Delete的基本方法。它们是:
- 添加/删除单个项目,
- 添加/删除多个项目,
- 添加/删除多个项目并创建DataContext。
每个单独的操作由Action定义,通过调用链传播。
对于删除:
dataContext.TrackInfos.Attach(i);
dataContext.TrackInfos.DeleteOnSubmit(i);
Remove(i);
添加:
dataContext.TrackInfos.InsertOnSubmit(i);
Add(i);
Add(...TrackInfo track)
或Add(...string path)
,但这需要一些运行时解析 - 使用巧妙放置的dynamic
是常见的解决方案…… - Alexei Levenkov