我有一个WCF服务,它公开了一堆[OperationContract]
个对各种类型的集合执行操作。
现在几乎每个实现都是这样的:
public void PerformSomeOperation(List<SomeType> someCollection) {
// store the exceptions that might be thrown during the operation
var exceptions = new List<Exception>();
foreach (var item in someCollection) {
try {
this.PerformSomeOperation(someParameters);
}
catch (Exception exception) {
exceptions.Add(exception);
}
}
// Throw the exceptions here after the loop completes.
if (exceptions.Count > 0) throw new AggregateException(exceptions);
}
因此,虽然this.PerformSomeOperation(...)
部分在实际实现之间发生了变化,但骨架的其余部分保持不变。因此,动态注入this.PerformSomeOperation(...)
部分的想法。
最优雅的解决方案是什么?当然,我可以在外部方法的参数列表中传递要作为字符串执行的操作的方法名称,并使用反射来调用方法(.GetMethod(...)
),但我希望有一些优雅的Lambda或Delegate构造。 / p>
答案 0 :(得分:3)
为什么不使用delegates?这些基本上是函数指针。
因此,您的常规DoWork方法包含Action:
public void DoWork(Action<List<SomeType>> myDelegate)
{
var exceptions = new List<Exception>();
foreach (var item in someCollection)
{
try {
myDelegate(someParameters);
}
catch (Exception exception) {
exceptions.Add(exception);
}
}
// Throw the exceptions here after the loop completes.
if (exceptions.Count > 0) throw new AggregateException(exceptions);
}
然后使用指向您自己的函数PerformSomeOperation
DoWork(PerformSomeOperation);
现在您可以切换可以使用的方法。
DoWork(PerformOtherOperationWithSameSignature)
答案 1 :(得分:2)
在这种情况下,Template method模式看起来很方便。
您可以定义包含方法框架的基类,如下所示:
public abstract class AbstractProcessor<T>
{
public void ProcessData(List<T> data)
{
var exceptions = new List<Exception>();
foreach (var item in data)
{
try
{
ProcessDataInternal(item);
}
catch (Exception exception)
{
exceptions.Add(exception);
}
}
if (exceptions.Count > 0) throw new AggregateException(exceptions);
}
protected abstract void ProcessDataInternal(T data);
}
然后你应该定义具体的实现并覆盖ProcessDataInternal
方法:
public class ConcreteProcessor<T> : AbstractProcessor<T>
{
protected override void ProcessDataInternal(T data)
{
// This implementation simply writes data to the console.
Console.WriteLine(data);
}
}
客户端示例:
AbstractProcessor<string> processor = new ConcreteProcessor<string>();
processor.ProcessData(new List<string> { "Hello", "World" });
答案 2 :(得分:1)
使用辅助方法
public void YourServiceMethod()
{
var collection = GetSomeDate();
DoWork(collection, item => PerformSomeOperation(someParameters));
}
private void DoWork(List<SomeType> collection, Action<SomeType> itemProcessor)
{
var exceptions = new List<Exception>();
foreach (var item in collection)
{
try
{
itemProcessor(someParameters);
}
catch (Exception exception)
{
exceptions.Add(exception);
}
}
// Throw the exceptions here after the loop completes.
if (exceptions.Count > 0) throw new AggregateException(exceptions);
}
或使用扩展方法:
public void YourServiceMethod()
{
var collection = GetSomeDate();
collection.DoWork(item => PerformSomeOperation(someParameters));
}
public class ListExtensions
{
public void DoWork(this List<SomeType> collection, Action<SomeType> itemProcessor)
{
var exceptions = new List<Exception>();
foreach (var item in collection)
{
try
{
itemProcessor(someParameters);
}
catch (Exception exception)
{
exceptions.Add(exception);
}
}
// Throw the exceptions here after the loop completes.
if (exceptions.Count > 0) throw new AggregateException(exceptions);
}
}
抛出一些泛型(支持所有类型):
public void YourServiceMethod()
{
var collection = GetSomeDate();
collection.ProcessList(item => PerformSomeOperation(someParameters));
}
public class ListExtensions
{
public void ProcessList<T>(this IEnumerable<T> collection, Action<T> itemProcessor)
{
var exceptions = new List<Exception>();
foreach (var item in collection)
{
try
{
itemProcessor(someParameters);
}
catch (Exception exception)
{
exceptions.Add(exception);
}
}
// Throw the exceptions here after the loop completes.
if (exceptions.Count > 0) throw new AggregateException(exceptions);
}
}