Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / WCF

Creating WCF Service Extensibility through MEF (Managed Extensibility Framework)

5.00/5 (2 votes)
8 Sep 2010CPOL3 min read 30K  
How to create WCF service extensibility through MEF

Recently, I was working on an application integration design wherein I wanted to expose service operations as extensibility points. By opening up the service operations for extensibility, I wanted to create a simple message bus which can be tapped into for application integration needs without making any changes to the existing implementation. The extensibility point will expose the operations of service to other components which will get a chance to act upon service requests.

I considered few design approaches to accomplish this, however I found most of the approaches to be intrusive to the existing implementation. I was looking for something which will be loosely coupled to the existing service implementation and really be like plug-and-play, without many code changes.

The first obvious thought was to look at IoC(Inversion of Control) and DI(Dependency Injection) along with WCF extensibility points. After looking all the available WCF extensibility points, it was easy to zero down on Parameter Inspector (IParameterInspector) as it gives access to the operation name and parameters. If we know the operation being called along with parameters and all the extensions implemented for that specific service, it would be just a matter of loading the extensions and calling the operation.

When you look at IoC/DI space, there are few seemingly overlapping options from Microsoft itself, like Unity application block from P&P, Managed add-in framework (MAF) in System.AddIn namespace and the latest entrant Managed Extensibility Framework (MEF). At a high level, all of these are composition engines, however MEF looked like specialized IoC container with added bells and whistles around DI. MEF is optimized around ‘discovery of unknown parts’ rather than just ‘registration of known parts’, this is what made MEF an interesting option for the problem I was trying to solve.  Another consideration was that MEF is bundled with .NET Framework 4.0, so no more libraries to update and move around. There is a nice post about Ten Reasons to use the Managed Extensibility Framework.

After a little bit of playing around with MEF, the following looked like the emerging pattern for the problem I was trying to solve.

 WCFandMEF

I defined an attribute (named ‘ServiceOperationExtensibility’) which implements IOperationBehavior interface and adds IParameterInspector DispatchBehavior. This attribute can be applied to an operation which needs to be exposed as extensibility point as shown below:

C#
1: [OperationContract]
2: [ServiceOperationExtensibility]
3: string OperationA(int param1, string param2);

A class implementing IParameterInspector (named ‘ExtensibilityInspector’) will accept the service contract type as constructor parameter.

C#
   1: ExtensibilityInspector extensibilityInspector = 
           new ExtensibilityInspector(operationDescription.DeclaringContract.ContractType);
   2: dispatchOperation.ParameterInspectors.Add(extensibilityInspector);

The ExtensibilityInspector simply gets an instance of ExtensibilityManager and passes the service contract type, operation name and arguments in ‘BeforeCall’ method of IParameterInspector interface.

C#
1: public object BeforeCall(string operationName, object[] inputs)
2: {
3:     ExtensibilityManager.Instance.InvokeExtension(this.ServiceContractType, operationName, inputs);
4:     return null;
5: }

The ExtensibilityManager is responsible for discovering and loading the extension components and calling the operation. The extension components needs to implement contract of service being extended. The component needs to decorate the class with MEF ‘Export’ attribute, this attribute would allow it to be discovered by MEF catalog.

C#
1: [Export(typeof(ProductService.IProductService))]
2: public class ProductServiceExtension1:ProductService.IProductService
3: {
4:     //Implementation removed for brevity
5: }

The ExtensibilityManager creates MEF catalog from assemblies present in designated directory. So the extension components need to be simply dropped into the designated directory (I have named this directory ‘Extensions’).

C#
1: private void Compose()
2: {
3:     var Catalog = new AggregateCatalog();
4:     Catalog.Catalogs.Add(new DirectoryCatalog(@".\Extensions"));
5:     this.Container = new CompositionContainer(Catalog);
6:     this.Container.ComposeParts(this);
7: }

InvokeExtension method of ExtensibilityManager created instance of MEF ImportDefinition based on the passed service contract type. It calls TryGetExports method on the previously created container to get all the extensions of specific type.

C#
 1: public void InvokeExtension(Type contractType, string operationName,object[] arguments)
 2: {
 3:     ImportDefinition importDefinition = new ImportDefinition
 (i => i.ContractName.Equals(contractType.FullName),
 contractType.FullName, ImportCardinality.ZeroOrMore, false, false);
 4:     AtomicComposition atomicComposition = new AtomicComposition();
 5:     IEnumerable<Export> extensions = null;
 6:
 7:     bool exportDiscovery = this.Container.TryGetExports
 (importDefinition, atomicComposition, out extensions);
 8:
 9:     if (extensions != null && extensions.Count<Export>() > 0)
10:     {
11:         foreach (Export extensionExport in extensions)
12:         {
13:             //ToDo: spawn a thread and do work there instead of doing it on the calling thread
14:             contractType.InvokeMember(operationName,
System.Reflection.BindingFlags.InvokeMethod, null, extensionExport.Value, arguments);
15:         }
16:     }
17: }

After getting the extensions, we can invoke the operation on each of the extension components. Please note that in this sample, I have directly called InvokeMember operation on the type instance, in production code you will spawn a thread instead of doing it on the calling thread.

Overall, this turned out to be a good solution, though there is a space for improvement to make it more fault tolerant and scalable. Depending upon your scenario, you need to build good security around the extensibility points and components, which I have completely omitted here.

The sample code can be downloaded from the following link. The sample service (named ‘IProductService’) is hosted in IIS, you can use WCFTestClient to invoke the operations. I have added one extension component in the solution which simply writes an entry to Windows event log on invocation of the operation.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)