Posterous theme by Cory Watilo

Adding context awareness to a fluent interface with the decorator pattern

I recently developed and released the first version of my custom programming model for the Managed Extensibility Framework (MEF). One of the things I included in the extension was a Fluent Definition Provider, a fluent interface used describe composable parts in a way that the programming model can consume them. A composable part used, in my extension, is defined with the help of a type name and collections of exports and imports.


The first version of the fluent interface looked similar to the following piece of code

1: public class FluentDefinitionProvider  2: {  3:     public FluentDefinitionProvider()  4:     {  5:     }  6:   7:     public FluentDefinitionProvider AddMetadata(string name, object value)  8:     {  9:         // Implementation omitted for clarity. 10:         return this; 11:     } 12:  13:     public FluentDefinitionProvider AddRequiredMetadata(string name) 14:     { 15:         // Implementation omitted for clarity. 16:         return this; 17:     } 18:  19:     public FluentDefinitionProvider Export<T>(Expression<Func<T, object>> exportExpression) 20:     { 21:  22:         // Implementation omitted for clarity. 23:         return this; 24:     } 25:  26:     public FluentDefinitionProvider Import<T>(Expression<Func<T, object>> importExpression) 27:     { 28:         // Implementation omitted for clarity. 29:         return this; 30:     } 31:  32:     public FluentDefinitionProvider WithContract(string contractName) 33:     { 34:         // Implementation omitted for clarity. 35:         return this; 36:     } 37: }

At first glance it might look like the interface violates the single responsibility principle because there is no ‘starter method’ for  defining a composable part, only method to define exports and imports, as well as method for altering their state. Looks can be deceiving and without showing you the full implementation of the class it’s impossible to know that internally the provider automatically manages the composable part definitions by inspecting the generic argument of the export and export methods. Also please note that the expression tree parameters or the export and import methods are implementation details of the class and it not related to the design of the fluent interface.


Each time the export of import method is called, the provider tries to retrieve a composable part which matches type of the the generic argument and use that as the active composable part. If no match could be found it will create and store one for the type. So in fact the interface does not violate the single responsibility principle, it most definitely is used to define composable part but its been written in a such a way that the consumer doesn’t explicitly have to define the composable part. This also leaves for a nicer user experience since export and imports for a specific type doesn’t have to be declared sequentially if you don’t want to.


The one thing that really annoyed me with this implementation was the fact that the interface contained methods which could be called out of order, for example AddRequireMetadata is only valid on an import and AddMetadata is only valid on an export, resulting in either an exception being thrown or having me write code to detect it and gracefully handle it.


So I decided I wanted to prevent methods from being called out of order, but I really didn’t want to have to include code in each method to make sure it was called in a valid context. I needed a better design of the fluent interface, one that would solve my problem without having to track the state in each method. What I needed was a way to make the fluent interface context aware so when I, for example, was defining an import I would only see the method that applied to an import and the same for an export.


After some thinking I decided I would use the decorator design pattern to solve my problems. The decorator pattern enables you to add (or decorate) a class with more functionality at runtime. Wikipedia lists several possible implementations of the pattern and the one I choose to go with was to create wrappers around my provider. So the FluentDefinitionProvider was rewritten to have an interface similar to


1: public class FluentDefinitionProvider  2: {  3:     public FluentDefinitionProvider()  4:     {  5:     }  6:   7:     public ExportDecorator Export<T>(Expression<Func<T, object>> exportExpression)  8:     {  9:         var decorator = 10:             new ExportDecorator(this); 11:         return decorator.Export<T>(exportExpression); 12:     } 13:  14:     public ImportDecorator Import<T>(Expression<Func<T, object>> importExpression) 15:     { 16:         var decorator = 17:             new ImportDecorator(this); 18:         return decorator.Import<T>(importExpression); 19:     } 20: }

The most obvious change is the reduction in available methods. The surface of the interface has been reduced to a minimum, which helps with the discoverability and usability. The second thing worth noticing is that the return type of the two method has changed from being of the type FluentDefinitionProvider into ExportDecorator and ImportDecorator. The decorators wrap the FluentDefinitionProvider to expose a specialized view for working with imports and exports.


I should also mention that there is also a public property, on the FluentDefinitionProvider, which is used to expose the available composable parts. For the sake of the context awareness this could just as well have been made internal instead of public, but making is public suited this particular interface.


1: public class FluentDefinitionProvider  2: {  3:     public FluentDefinitionProvider()  4:     {  5:     }  6:   7:     public Collection<PartDescription> Descriptions { get; protected set; }  8:   9:     public ExportDecorator Export<T>(Expression<Func<T, object>> exportExpression) 10:     { 11:         var decorator = 12:             new ExportDecorator(this); 13:         return decorator.Export<T>(exportExpression); 14:     } 15:  16:     public ImportDecorator Import<T>(Expression<Func<T, object>> importExpression) 17:     { 18:         var decorator = 19:             new ImportDecorator(this); 20:         return decorator.Import<T>(importExpression); 21:     } 22: }

The decorators uses this property to get access to the part and the export/import which is currently in context (basically it uses a Linq extension to get the last part and the last export/import depending on the decorator) so that it’s state can be altered. If you look closely you see that the actual implementations of the export and import method have been moved from the FluentDefinitionProvider into the decorators. This means that the methods on the interface work as starter methods and nothing more, i.e they help you get a hold of the correct context.


There was some functionality which I wanted both of my decorators to share, so I created the Decorator base class and put the shared functionality in that class.


1: public abstract class Decorator  2: {  3:     protected Decorator(FluentDefinitionProvider provider)  4:     {  5:         this.Provider = provider;  6:         this.CurrentPart = this.Provider.Descriptions.Last();  7:     }  8:   9:     public PartDescription CurrentPart { get; protected set; } 10:  11:     public FluentDefinitionProvider Provider { get; protected set; } 12:  13:     public ExportDecorator Export<T>(Expression<Func<T, object>> exportExpression) 14:     { 15:         // Implementation omitted for clarity. 16:  17:         var decorator = 18:             new ExportDecorator(this.Provider) { CurrentPart = this.GetPart(typeof(T)) }; 19:         decorator.CurrentPart.Exports.Add(description); 20:  21:         return decorator; 22:     } 23:  24:     public ImportDecorator Import<T>(Expression<Func<T, object>> importExpression) 25:     { 26:         // Implementation omitted for clarity. 27:  28:         var decorator = 29:             new ImportDecorator(this.Provider) { CurrentPart = this.GetPart(typeof(T)) }; 30:         decorator.CurrentPart.Imports.Add(description); 31:  32:         return decorator; 33:     } 34: }

Basically the main functionality of the Decorator base class is to provide the implementations of the export and import methods. By having them in the base class, they are shared across the ExportDecorator and ImportDecorator and that enables me to switch context, so for example when I’m done adding an import I can start adding an export (or another import) since that method will always been in context. There are some other small properties to help reduce the amount of code needed in the subclasses and to keep track of the provider instance which is being decorated.


With the base class in place, the ExportDecorator and ImportDecorator classes can be implemented. They are going to provide a context specific view of the provider, i.e only show the method which are valid to call in the specific context the provider currently is in.


Here are partial implementation of the ExportDecorator and ImportDecorator classes.


1: public class ExportDecorator : Decorator  2: {  3:     public ExportDecorator(FluentDefinitionProvider provider)  4:         : base(provider)  5:     {  6:     }  7:   8:     public ExportDecorator AddMetadata(string name, object value)  9:     { 10:         this.CurrentPart.Exports.Last().Metadata.Add(name, value); 11:         return this; 12:     } 13:  14:     public ExportDecorator WithContract(string contract) 15:     { 16:         this.CurrentPart.Exports.Last().Contract = contract; 17:         return this; 18:     } 19: } 20:  21: public class ImportDecorator : Decorator 22: { 23:     public ImportDecorator(FluentDefinitionProvider provider) 24:         : base(provider) 25:     { 26:     } 27:  28:     public ImportDecorator AddRequiredMetadata(string name) 29:     { 30:         this.CurrentPart.Imports.Last().RequiredMetadata.Add(name); 31:         return this; 32:     } 33:  34:     public ImportDecorator AllowDefault(bool allowDefault) 35:     { 36:         this.CurrentPart.Imports.Last().AllowDefault = allowDefault; 37:         return this; 38:     } 39:     40:     public ImportDecorator WithContract(string contract) 41:     { 42:         this.CurrentPart.Imports.Last().Contract = contract; 43:         return this; 44:     } 45: }

And that’s more or less how you can add context awareness to a fluent interface. Each of the decorators exposes a specialized view of the interface. It’s not possible for me to call AddMetadata on an import or AllowDefault on an export, the compiler will tell me I’m not behaving if I try.


There are some other added benefits to this approach. First of all it delivers a very nice intellisense experience and second of all, thanks to the fact that you are working with concrete classes, you open up the possibility to extend the implementation at a later stage with the help of extensions methods!


If you want to take a look at the full implementation of the FluentDefinitionProvider, then visit the MEF Contrib and download the source code release. The class is located under the MefContrib.Models.Provider.Definitions.Fluent namespace.