最近我似乎正在处理大量的请求/响应内容,并且我想创建一些通用的东西。
我有以下内容,但我不满意创建多个ifs语句,我想避免使用它们。
这个想法是这样的:
无论请求/响应过程如何。 如何在我的通用请求处理程序中删除这些if语句?
代码
class Program
{
private static void Main()
{
IRequestResponseFactory factory = new RequestResponseFactory();
var customerRequest = new CustomerRequest { Name = "Joe", Surname = "Bloggs" };
var customerResponse = factory.ProcessRequest<CustomerRequest, CustomerResponse>(customerRequest);
var billRequest = new BillRequest() { Amount = 100m };
var billResponse = factory.ProcessRequest<BillRequest, BillResponse>(billRequest);
Console.WriteLine(billResponse.Success);
Console.WriteLine(customerResponse.Success);
Console.ReadKey();
}
}
public class CustomerRequest : IRequestData<CustomerResponse>
{
public string Name { get; set; }
public string Surname { get; set; }
}
public class CustomerResponse
{
public bool Success { get; set; }
}
public class BillRequest : IRequestData<BillResponse>
{
public decimal Amount { get; set; }
}
public class BillResponse
{
public bool Success { get; set; }
}
public interface IRequestData<TResponse>
{
}
public interface IRequestHandler<TRequest, TResponse> where TRequest : IRequestData<TResponse>
{
TResponse ProcessRequest(TRequest request);
}
public interface IRequestResponseFactory
{
TResponse ProcessRequest<TRequest, TResponse>(TRequest request) where TRequest : IRequestData<TResponse>;
}
class RequestResponseFactory : IRequestResponseFactory
{
public TResponse ProcessRequest<TRequest, TResponse>(TRequest request) where TRequest : IRequestData<TResponse>
{
var handler = new GenericRequestHandler<TRequest, TResponse>();
TResponse response = handler.ProcessRequest(request);
return response;
}
}
public class GenericRequestHandler<TRequest, TResponse> : IRequestHandler<TRequest, TResponse> where TRequest : IRequestData<TResponse>
{
public TResponse ProcessRequest(TRequest request)
{
var response = default(TResponse);
//How do I avoid this if statements????
if (request is IRequestData<CustomerResponse>)
{
var tempResponse = new CustomerResponse { Success = true };
response = (TResponse)Convert.ChangeType(tempResponse, typeof(TResponse));
return response;
}
if (request is IRequestData<BillResponse>)
{
var tempResponse = new BillResponse { Success = false };
response = (TResponse)Convert.ChangeType(tempResponse, typeof(TResponse));
return response;
}
return response;
}
}
答案 0 :(得分:7)
您可以使用专门的GenericRequestHandler<TRequest, TResponse>
替换IRequestHandler
类,让工厂通过反射跟踪所有可用的处理程序。
具体而言,这些可能是处理程序:
public class CustomerRequestHandler : IRequestHandler<CustomerRequest, CustomerResponse>
{
public CustomerResponse ProcessRequest(CustomerRequest request)
{
return new CustomerResponse { Success = true };
}
}
public class BillRequestHandler : IRequestHandler<BillRequest, BillResponse>
{
public BillResponse ProcessRequest(BillRequest request)
{
return new BillResponse { Success = false };
}
}
现在,工厂将执行以下操作,而不是仅将调用转发到包含if
丑陋的通用处理程序:
IRequestHandler<TRequest, TResponse>
TRequest
类型,值是处理程序类型这是工厂类的可能实现:
class RequestResponseFactory : IRequestResponseFactory
{
private readonly Dictionary<Type, Type> _requestHandlerTypes;
public RequestResponseFactory()
{
_requestHandlerTypes =
typeof(RequestResponseFactory).Assembly.GetTypes()
.Where(t => !t.IsAbstract)
.Select(t => new
{
HandlerType = t,
RequestType = GetHandledRequestType(t)
})
.Where(x => x.RequestType != null)
.ToDictionary(
x => x.RequestType,
x => x.HandlerType
);
}
private static Type GetHandledRequestType(Type type)
{
var handlerInterface = type.GetInterfaces()
.FirstOrDefault(i =>
i.IsGenericType &&
i.GetGenericTypeDefinition() == typeof(IRequestHandler<,>));
return handlerInterface == null ? null : handlerInterface.GetGenericArguments()[0];
}
public TResponse ProcessRequest<TRequest, TResponse>(TRequest request) where TRequest : IRequestData<TResponse>
{
if (!_requestHandlerTypes.ContainsKey(typeof(TRequest)))
throw new ApplicationException("No handler registered for type: " + typeof(TRequest).FullName);
var handlerType = _requestHandlerTypes[typeof(TRequest)];
var handler = (IRequestHandler<TRequest, TResponse>)Activator.CreateInstance(handlerType);
return handler.ProcessRequest(request);
}
}
包含工作样本的完整程序位于http://ideone.com/TxRnEi。
输出与原始程序的输出相同,但现在程序允许您添加新类型的请求和新类型的处理程序,并且能够在运行时动态使用它们,而无需编写长if
/ case
语句,用于指定何时使用它们。