In my last post I talked about how to register dynamically (at runtime) a WCF instance without the need to have an existing .svc file or something in the configuration file (<serviceHostingEnvironment><serviceActivations>).
In this post, we are going deeper in the "Dynamic" domain and we would like to not only host our service dynamically, but also to create the actual service contracts and service operations (and its metadata to support WSDL generation) dynamically (at runtime).
You might be asking yourself: Why on earth anyone would like to create a WCF service (and contracts with methods) at runtime?
Well, there is a big chance that you never need to do something like this (I have lived without this so far, and our current projects are running in production very well) but we are building the next version of our development platform (the elusive project codename "E2" I talked about in my previous post) and in that context we need a way to generate the API that our "Business Models, Modules and Process" define. Those artifacts are completely created by our Business Analyst users and they don't require ANY CODING at all, so why we would settle for less when talking about the exposed APIs of those things.
In the sample code you can download below there are not one but two different approaches to this:
- Using Reflection.Emit to create at runtime a service class that implement the desired operations (methods).
- Using the "ContractDescription" class to create and inject at runtime the service metadata that resembles the desired operations (methods).
Both approaches resolve the service metadata creation, the first by creating a class and letting the WCF runtime to generate the service description metadata in the normal way, and the other build and inject this service description metadata from scratch. Both methods works equally well but I tend to preffer the second because generating and loading a dynamic type in the running process (or AppDomain) have the drawback that is difficult to unload those generated Types and replace them with new versions when the business metadata changes (remember that Business Analysts are doing that, and they are free to change anything they need).
Having said that, I know that it would be possible to unload a generated Type by means of custom AppDomains, but is more work and there are security and performance issues associated with this. By using a metadata only approach we eliminate this problems altogether.
So far we resolved the metadata generation part, but the actual execution of those pesky "Business Process" is not mentioned anywhere, and that's because that is the easy part! :)
WCF already provides all the extensibility you need to intercept the execution of ServiceOperations and do wherever you need, and that's exactly what I do in both examples. I have created an "OperationInvoker" class implementing some WCF interfaces (IOperationInvoker and IOperationBehavior for the injection part) so feel free to explore them, but they are pretty simple. When constructing the metadata we inject it into the "OperationDescription" behaviors collection, check the "CreateOperationDescription" method in the "Service5.cs" project file.
Well, enjoy the code and let me know if have any comments.
Source code download from here: DynamicService2.zip
Andrés G Vettori, CTO, VMBC