using System;
using System.Collections.Generic;
using System.Linq;
internal class Program
{
public 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
{
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);
}
}
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 };
}
}