Jason v0.2: configuration improvements and breaking changes
As we have already discussed Jason is an infrastructure framework to handle the “Command” portion of the CQRS pattern, due to some customer feedback and requests today we released a brand new version of the whole toolkit adding a lot of improvements and, unfortunately, some breaking changes.
One configuration to rule them all
In the previous Jason version there was one different configuration per hosting type, basically in order to host Jason as a WCF service the developer needed to build a specific configuration that was different from the one required to host Jason as a WebAPI controller. This difference leaded to one big issue: you simply cannot host, in the same application, a Jason API controller and a Jason WCF service.
In v0.2 we solved this scenario rebuilding the whole configuration stuff:
var jasonConfig = new DefaultJasonServerConfiguration ( pathToScanForAssemblies: Path.Combine( AppDomain.CurrentDomain.BaseDirectory, "bin" ), assemblySelectPattern: assemblySelectPattern ); jasonConfig.AddEndpoint( new Jason.WebAPI.JasonWebAPIEndpoint() { TypeNameHandling = TypeNameHandling.Objects } ); jasonConfig.AddEndpoint( new Jason.Server.JasonWcfEndpoint() { CommandsSelector = t => { return t.IsAttributeDefined<DataContractAttribute>() && ( t.Name.EndsWith( "Command" ) || t.Name.EndsWith( "CommandResponse" ) ); } } ); jasonConfig.Initialize();
We are building just one single configuration adding 2 different endpoints each one with its own configuration peculiarities.
Inversion of control support
Jason heavily relies on the Inversion of Control pattern to work and depends on an Inversion of Control container but we do not want, as in previous versions, to force the user to introduce an IoC container in the solution only to support Jason and we especially do not want you to remember to register the internal Jason type that are required to work.
In v0.2 we leverage the power of the Radical built-in PuzzleContainer (that is now available in all Radical versions) to support the IoC Jason needs, the internal container is exposed by the configuration via the Container property and can be used to register custom types required during the Jason usage.
Obviously the default internal container can be easily replaced in order to integrate Jason in your development lifecycle using your favorite container of choice. In order to achieve that it is enough to replace the built-in container via the configuration Container property where the IJasonContainer is just a proxy interface to abstract the container concept.
Here is a sample implementation to inject Castle Windsor:
public class WindsorJasonContainerProxy : Jason.Configuration.IJasonContainer { IWindsorContainer container; public WindsorJasonContainerProxy( IWindsorContainer container ) { this.container = container; } public void RegisterAsTransient( IEnumerable<Type> contracts, Type implementation ) { this.container.Register( Component.For( contracts ).ImplementedBy( implementation ).LifestyleTransient() ); } public void RegisterAsSingleton( IEnumerable<Type> contracts, Type implementation ) { this.container.Register( Component.For( contracts ).ImplementedBy( implementation ).LifestyleSingleton() ); } public void RegisterInstance( IEnumerable<Type> contracts, object instance ) { this.container.Register( Component.For( contracts ).Instance( instance ).LifestyleSingleton() ); } public void RegisterTypeAsTransient( Type implementation ) { this.container.Register( Component.For( implementation ).LifestyleTransient() ); } public void RegisterTypeAsSingleton( Type implementation ) { this.container.Register( Component.For( implementation ).LifestyleSingleton() ); } public IEnumerable<T> ResolveAll<T>() { return this.container.ResolveAll<T>(); } public T Resolve<T>() { return this.container.Resolve<T>(); } public IEnumerable<object> ResolveAll( Type t ) { return this.container.ResolveAll( t ).Cast<Object>(); } public object Resolve( Type t ) { return this.container.Resolve( t ); } public void Release( object instance ) { this.container.Release( instance ); } }
As said just a trivial proxy that can be used in the following manner:
var jasonConfig = new DefaultJasonServerConfiguration( Path.Combine( AppDomain.CurrentDomain.BaseDirectory, "bin" ) ) { Container = new WindsorJasonContainerProxy( yourWindsorInstance ) };
After that Jason will use your container to register its own required types and to resolve at runtime the required components.
Next time: Jason retry policies.
.m