您好想知道是否有更好的方法来删除其他if语句并使用策略模式。 任何想法?
public async Task<TResponse> HandleResponseAsync<TRequest, TResponse>(TRequest item)
where TResponse : class, new()
{
TResponse result = default(TResponse);
Type currentResponseType = typeof(TResponse);
if (currentResponseType == typeof(MyResponseA))
{
result = //dosomething
}
else if (currentResponseType == typeof(MyResponseB))
{
result = //dosomething
}
else if (currentResponseType == typeof(MyResponseC))
{
result = //dosomething
}
return result;
}
答案 0 :(得分:7)
在泛型方法中使用特定的子类是一种非常危险的方法,因为它通过将您锁定到泛型方法内的类列表来限制未来的灵活性。它还抛弃了使其成为通用方法所能获得的大部分优势。
由于您已经需要无参数构造函数,因此一种方法是为您的TResponse
提供一个接口,并使用该接口回调实例以获得正确的结果:
interface IResponse {
void Configure(); // Use custom parameters if necessary
}
public async Task<TResponse> HandleResponseAsync<TRequest, TResponse>(TRequest item) where TResponse : class, new(), IResponse {
TResponse result = new TResponse();
result.Configure(...);
}
现在来自if-then-else块的代码将进入相应Configure
实现的IResponse
方法:
class MyResponseA : IResponse {
public MyResponseA() {}
public void Configure() {
// dosomething from the first IF
}
}
class MyResponseB : IResponse {
public MyResponseB() {}
public void Configure() {
// dosomething from the second IF
}
}
注意:如果不同的实例需要传递HandleResponseAsync
的不同信息,事情可能会变得棘手。在这种情况下,您还应该创建一个对象,其中包含任何实现可能需要的所有信息,以便完成其Configure
方法。
答案 1 :(得分:5)
如果你打开泛型的类型,你可能做错了。泛型应该泛型。您编写的代码不是通用的,它的非常脆弱,而且泛型使它更多,而不是更简单。
在这里,让我为你重写一下:
if (currentResponseType == typeof(MyResponseA))
return (TResponse) HandleResponseA(item);
else if (currentResponseType == typeof(MyResponseB))
return (TResponse) HandleResponseB(item);
else if (currentResponseType == typeof(MyResponseC))
return (TResponse) HandleResponseC(item);
如果通过该方法有三种可能的代码路径,那么只需编写三种方法HandleResponseA
,HandleResponseB
,HandleResponseC
即可。 这就是你已经做过的事情,你只需将每个方法的主体作为if
的主体。这里没有储蓄使它们成为一种方法;你刚刚做了一个脆弱的,过于复杂的方法。现在我们已经重构了您的方法,我们发现我们可以完全删除该方法,只需直接调用适当的处理程序。
另外,考虑一下你的不良来电者!在通话网站上,没有令人信服的理由倾向于HandleResponseAsync<Giraffe, MyResponseB>(giraffe)
更好HandleResponseB(giraffe)
;如果有三种方法而不是一种方法,呼叫站点更短,更清晰,更安全。
此外,如果此处提供的服务100%取决于响应对象的类型,那么为什么这不是响应对象的关注?为什么呼叫网站实际上不是MyResponseB.Handle(giraffe)
?方法可以是响应类型的静态方法。如果您要编写三个方法体,每种类型一个,那么将它们放在该类型上。
答案 2 :(得分:1)
在 c#7 中,您可以使用switch
var response = new TRsponse();
switch (response)
{
case MYResponseB b:
break;
case MYResponse a:
break;
}
我们正在推广switch语句,以便:1。您可以打开任何类型(不仅仅是原始类型)2.Patterns可用于case子句3.Case子句可以有其他条件
这是c#7中的新功能:
https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/