DarioSantarelli.Blog(this);

Archive for December, 2011

Using MEF in a Request/Response Service Layer

Posted by dariosantarelli on December 30, 2011


In a project of mine I’m using a simple Request/Response service layer very similar to the amazing Davy Brion’s Agatha project. Everything started a few time ago when I was searching for a smart way to design a client-server infrastructure which was focused on messages and not on operations. This layer would be not only a classic WCF-based service, but also a some kind of in-process facade to my business layer where I could centralize any cross cutting concern. So I was focused on the capability of moving my service layer and its business logic to a separate machine and hosting it through WCF without any significant modifications to my code (admitting that service layer doesn’t share state with upper layers like the presentation layer). After reading Davy’s “Why I Dislike Classic Or Typical WCF Usage” , I was convinced to address myself to one service contract with one service operation, avoiding to spend time thinking about how to design and implement service contracts and operations. In this way, the first (great) advantage I got is that I can add functionalities simply defining a request message, a response message and a request handler which executes the logic needed between a request receiving and a response sending. Very simple and effective!

Overview of the service layer

Everything starts from an interface called IRequestHandler:

public interface IRequestHandler 
{
  Response HandleRequest(Request request);
}

Request and Response are empty base abstract classes:

public abstract class Request {}
public abstract class Response {}

Now let’s define a simple rule: every concrete request type must be corresponded by a concrete response type. The idea is to basically consider each service operation as a request which must have a response. For each request you define, you need to provide an handler which does whatever it needs to do to handle the request and returns a response. In my solution, a simple generic base request handler has been defined in the following way:

public abstract class RequestHandlerBase<TRequest, TResponse> : IRequestHandler 
                                                              where TRequest : Request 
                                                              where TResponse : Response 
{
    public Response HandleRequest(Request request)
    {
        return HandleRequest((TRequest)request);
    }

    public abstract TResponse HandleRequest(TRequest request);
}

For example, by inheriting this RequestHandlerBase base class, we could create a login request handler, which implements the business logic for validating a user:

public class LoginRequestHandler : RequestHandlerBase<LoginRequest, LoginResponse>
{
    public override LoginResponse HandleRequest(LoginRequest request)
    {
      // validate the user credentials contained in the LoginRequest 
      // and return a LoginResponse containing, for example, a session token 
    }
}

Having each request handler implemented in the same fashion as the LoginRequestHandler, I’d like to reach a service implementation like this:

public class MyService : IRequestHandler 
{
    private readonly IRequestHandlerProvider _requestHandlerProvider;

    public MyService(IRequestHandlerProvider requestHandlerProvider)
    {
        _requestHandlerProvider = requestHandlerProvider;
    }

    public Response HandleRequest(Request request)
    {
        return _requestHandlerProvider.GetRequestHandler(request.GetType()).HandleRequest(request);
    }
}

As you can see, the service itself implements the IRequestHandler interface and the actual implementation is very minimal: it’s just a small class which resolves the appropriate handler through an abstraction called IRequestHandlerProvider which internally may use an IoC container capable of resolving the request handler associated to a request type. Then, the service delegates the execution to an handler by passing the request to it, and finally it returns a typed response to the client.

Enter MEF

Now we could need a IoC container to resolve and create the instances of the request handlers. As shown in this post, you can use the Castle Windsor IoC container to use dependency injection. That basically allows you to register each valid request handler that is present, for example, in a given assembly. Even my purpose was to find a simple way to plug in request handlers defined in external assemblies, getting everything registered automatically in a centralized request handler provider when the application starts up. So, I was focused on MEF. What I tried to do is to treat each request handler as an extension, because in my project each tuple “Request-Response-Handler” represents an extension unit. Moreover,

  • MEF is an integral part of the .NET Framework 4
  • MEF offers a set of discovery approaches for locating and loading available extensions even in a “lazy” fashion
  • MEF allows tagging extensions with additonal metadata which facilitates rich querying and filtering so an extensibility element can provide metadata to exported items.

Following this philosophy, beyond the classic Export attribute I introduced a RequestHandlerMetadataAttribute useful for simplifying the process of resolving an handler related to a specific request type. So, the LoginRequestHandler defined before could be decorated as the following…

[Export(typeof(IRequestHandler))] // I am a request handler!!!
[RequestHandlerMetadata(typeof(LoginRequest))] // I can handle Login requests!!!
public class LoginRequestHandler : RequestHandlerBase<LoginRequest, LoginResponse>
{
  ... 
}

And here is the RequestHandlerMetadataAttribute definition.

public interface IRequestHandlerMetadata 
{
    Type RequestType { get; }
}

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class RequestHandlerMetadataAttribute : ExportAttribute 
{
    public Type RequestType { get; set; }

    public RequestHandlerMetadataAttribute(Type requestType)
        : base(typeof(IRequestHandlerMetadata))
    {
        RequestType = requestType;
    }
}

In order to allow us to access the metadata, MEF introduces a special kind of Lazy<T,M> that has attached metadata. M in this case is an interface (called “metadata view”) that contains only getter properties. MEF automatically generates a proxy class that implements this interface and it plugs all the metadata in for us. This is very cool! What is happening behind the scenes is that MEF is using reflection emit in order to construct the typed metadata view.

As result, I’ve used the metadata view IRequestHandlerMetadata to easily find the right handler for a request of a given type, as shown in the GetRequestHandler() method of the following MefRequestHandlerProvider.

public class MefRequestHandlerProvider : IRequestHandlerProvider 
{
    private readonly List<Lazy<IRequestHandler, IRequestHandlerMetadata>> _registeredHandlers =
                                              new List<Lazy<IRequestHandler, IRequestHandlerMetadata>>();

    public MefRequestHandlerProvider(IEnumerable<ComposablePartCatalog> catalogs)
    {
        foreach (var catalog in catalogs)
        {
            var container = new CompositionContainer(catalog);
            var exportedHandlers = container.GetExports<IRequestHandler, IRequestHandlerMetadata>();

            foreach (var exportedHandler in exportedHandlers)
            {
                foreach (var registeredHandler in _registeredHandlers)
                {
                    if (registeredHandler.Metadata.RequestType == exportedHandler.Metadata.RequestType)
                        throw new NotSupportedException(string.Format("A request handler for type {0} is already registered.",
                                                                      exportedHandler.Metadata.RequestType));
                }
            }

            _registeredHandlers.AddRange(exportedHandlers);
        }
    }

    public IRequestHandler GetRequestHandler(Type requestType)
    {
        var handler = _registeredHandlers.SingleOrDefault(r => r.Metadata.RequestType == requestType);
        if (handler != null) return handler.Value;
        throw new RequestHandlerNotFoundException(string.Format("No request handler has been found for type {0}", requestType));
    }
}

Putting all together, in the application startup I placed the following initialization code which uses the MefRequestHandlerProvider. As you may know, request handlers can be located inside catalogs (e.g. AssemblyCatalog, AggregateCatalog etc.). When using a client proxy, I need to expose just one method which never needs to be updated. That’s a good advantage!

// Server-Side 
var catalog = new AssemblyCatalog(typeof(IRequestHandler).Assembly);
var mefRequestHandlerProvider = new MefRequestHandlerProvider(new[] { catalog });
MyService service = new MyService(mefRequestHandlerProvider);

// Client-Side (when using a proxy)
LoginResponse response = (LoginResponse)serviceProxy.HandleRequest(new LoginRequest("username", "password"));
Console.WriteLine(response.AccessToken);

Conclusion

In this post I’ve tried to show how I used MEF to plug request handlers in a request/response service layer similar to Agatha. I have not written anything about serialization issues when exposing the service layer through WCF. Moreover, I haven’t treated any aspects about request handlers such as objects lifecycles or error management. I think that any question about these service layer insights can find good answers after reading the Davy Brion’s Request/Response Service Layer Series.

HTH

Posted in .NET Framework, Microsoft Technology, Programming | Tagged: , | 1 Comment »