[英]How can I use delegates/lambdas/Func<> to get rid of code reuse?
I have a web service where I find myself putting the exact same try/catch block in every method and I'm trying to eliminate that code reuse.我有一个 web 服务,我发现自己在每个方法中都放置了完全相同的 try/catch 块,并且我试图消除代码重用。
Here is a sample method (some code removed) where you can see #1/#2/#3 are the core calls and are very similar.这是一个示例方法(删除了一些代码),您可以在其中看到#1/#2/#3 是核心调用并且非常相似。
[HttpGet]
[Route("GetKeys")]
[Produces(MediaTypeNames.Application.Json)] // "application/json"
public async Task<EntityKeyPage> GetKeys([FromQuery] string company = "", [FromQuery] DocumentPaging documentPaging = null)
{
[...]
try
{
// Sometimes it's this #1
VendTableServiceGetKeysResponse getKeysResponse = await aifClient.getKeysAsync(getKeysRequest);
// Sometimes it's this #2
// VendTableServiceReadResponse readResponse = await aifClient.readAsync(readRequest);
// Sometimes it's this #3
// VendTableServiceFindKeysResponse findKeysResponse = await aifClient.findKeysAsync(findKeysRequest);
}
catch (System.ServiceModel.FaultException<AifFault> ex)
{
var message = this.GetAXMessage(ex);
aifClient.Abort();
throw new Exception(message);
}
catch (Exception e)
{
aifClient.Abort();
string errorMessage = e.Message != null ? e.Message : "";
errorMessage = e.InnerException != null ? errorMessage + "\n" + e.InnerException : errorMessage;
throw new Exception(errorMessage);
}
finally
{
aifClient.Close();
}
return getKeysResponse.EntityKeyPage;
}
Here is my attempt at a generic method I can use.这是我可以使用的通用方法的尝试。
private async Task<Out> MakeAIFCall<In, Out>(Func<In, Out> action, In @in)
{
Out @out;
try
{
@out = action(@in);
}
catch (System.ServiceModel.FaultException<AifFault> ex)
{
var message = this.GetAXMessage(ex);
aifClient.Abort();
throw new Exception(message);
}
catch (Exception e)
{
aifClient.Abort();
string errorMessage = e.Message != null ? e.Message : "";
errorMessage = e.InnerException != null ? errorMessage + "\n" + e.InnerException : errorMessage;
throw new Exception(errorMessage);
}
finally
{
aifClient.Close();
}
return @out;
}
I wrote that method based on my reading, but I can't figure out how to call it?我根据阅读编写了该方法,但我不知道如何调用它? It appears I normally would pass a method name, but in this case it would be an object+method (
aifClient.getKeysAsync(...)
/ aifClient.readAsync(...)
/ aifClient.findKeysAsync(...)
)?看来我通常会传递一个方法名称,但在这种情况下它将是一个对象+方法(
aifClient.getKeysAsync(...)
/ aifClient.readAsync(...)
/ aifClient.findKeysAsync(...)
)?
How do I call my method and or am I doing it wrong?我如何调用我的方法,或者我做错了什么?
This is my first attempt at calling it, but it's wrong:这是我第一次尝试调用它,但它是错误的:
var response = await MakeAIFCall<VendTableServiceGetChangedKeysRequest, VendTableServiceGetChangedKeysResponse>(aifClient.getKeysAsync, getKeysRequest);
The variables @out
and @in
were suggested by intellisense...I have no idea why the @
symbol is there or what it does.变量
@out
和@in
是由intellisense 建议的......我不知道为什么@
符号在那里或它的作用。
Since your methods are awaited we can almost safely assume that they return tasks (however there are other possibilities), so first of all you will need to change your method signature to something like this:由于等待您的方法,我们几乎可以安全地假设它们返回任务(但是还有其他可能性),因此首先您需要将方法签名更改为如下所示:
private async Task<Out> MakeAIFCall<In, Out>(Func<In, Task<Out>> action, In @in)
{
Out @out;
try
{
@out = await action(@in);
}
....
Second of all you can leverage existence of closures in C# so you will not need to provide a parameter:其次,您可以利用 C# 中存在的闭包,因此您无需提供参数:
private async Task<Out> MakeAIFCall<Out>(Func<Task<Out>> call)
{
Out @out;
try
{
@out = await call();
}
....
}
And use it like that:并像这样使用它:
await MakeAIFCall(() => aifClient.getKeysAsync(getKeysRequest));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.