lundi 12 décembre 2016

What is this design pattern name and what are the benefits of implementing it

The pattern implementation

    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 };
    }
}

http://ift.tt/2hmXyRV

What is this design pattern name?

Also, I am trying to understand the scenarios where this pattern will be of any use.

I can see that if you implement multiple RequestResponseFactories you can execute different handler, for the same pair of TRequest and TResponse. This looks like kind of IoC and can be useful in unit testing or for contextual binding.

However if you are already using IoC container in your app, does this pattern add anything to it?

Thanks.

Aucun commentaire:

Enregistrer un commentaire