José F. Romaniello

Las aventuras y desventuras de un codificador.

Today I have released a new version of the HqlAddin project, the version is 1.0.0.4550 – Alpha 2 (a.k.a. Green Popotito).

Green Popotito comes with a new amazing feature, intellisense for properties and entities. This is a great work that comes from Felice Pollano’s NhWorkbench, so kudos for him.

Before we continue, let me show you a short screencast of the tool:

 

How does this work?

You have to export (with MEF) your configuration in any assembly, hql addin will look the output path of the startup project and if it find an export will import the information to give you intellisense. Just write an export on any project, the build path can be anywhere. Follows the instructions here.

Any configuration of any version of NHibernate is ok. In order to update your intellisense (e.g. when you change your mappings) you will have to rebuild the solution ctrl + shift + b.

How to use the hql files?

You can read the full guide here.

Where do I get this?

You can download from the main website or simply from the Visual Studio Online Gallery of your Extension Manager. Read more here.

Provide feedback is mandatory

Please get involved with the project, provide some feedback, thoughts, issues or anything!

| More

I had an idea few days ago, about using an Enumerable Queryable as ServiceLocator, lets say a sequence of things that you can query.

I will explain this idea through simple tests. Suppose we have the following interface:

public interface IContainer
{
    IEnumerable<T> GetServices<T>();
    T GetService<T>();
}

1-It is a bad thing to ask to our ServiceLocator for all services so:

[Test]
public void WhenEnumeratingWithoutTypeThenThrowException()
{
    var container = new Mock<IContainer>();
    
    var sl = new QueryableLocator<object>(container.Object);
    
    sl.Executing(q => q.ToArray())
    .Throws<InvalidOperationException>()
    .And.ValueOf.Message
        .Should().Be.EqualTo("You must start with an OfType call.");
}

Prety easy to understand, if I try to enumerate for ALL services, just throw an exception

2-How to query all instances of a given type registered in the container.

[Test]
public void WhenEnumeratingWithOfTypeThenReturnAllInstancesOfTheGivenType()
{
    var container = new Mock<IContainer>();
    var serviceInstances = new []{"a", "b"};
    container.Setup(c => c.GetServices<string>())
             .Returns(serviceInstances);

    var sl = new QueryableLocator<object>(container.Object);
    sl.OfType<string>().ToArray()
            .Should().Have.SameValuesAs(serviceInstances);
}

I can query for all services implementing a given interface. Same stuff is on CommonServiceLocator.

3-How to get an instance of a given type

[Test]
public void WhenEnumeratingWithOfTypeAndCallingSingleThenResolveOnlyOneInstance()
{
    var container = new Mock<IContainer>();
    container.Setup(c => c.GetService<string>())
            .Returns("a");

    var sl = new QueryableLocator<object>(container.Object);
    sl.OfType<string>().Single()
        .Should().Be.Equals("a");
}

This is the most widely used scenario, doing sl.OfType().Single() is the same than commonServiceLocator.GetInstance()

4-Throw an exception when you try to do a Select, Count, Where, etc

[Test]
public void WhenExecutingAnUnrelatedLinqMethodThenThrowException()
{
    var container = new Mock<IContainer>();
    
    var query = new QueryableLocator<object>(container.Object);

    query.Executing(q => q.Count(s => true))
        .Throws<InvalidOperationException>()
        .And.ValueOf.Message
            .Should().Be.EqualTo("Count is not allowed over the service locator.");
}

Ok, this is all for now.

Advantages of QueryableServiceLocator over CommonServiceLocator

There are two big advantages:

  • You don’t need an extra assembly Microsoft.CommonServiceLocator. In fact IoC containers can provide their own implementation, so there is not need for an implementor assembly.
  • Easy to create Factories, you don’t need to write another interface/implementation for factories. Do you want a MessageHandlerFactory? var messageHandlerFactory = serviceLocator.OfType<IMessageHandler>().

TODOs

This is a rough idea, so far I don’t know how to handle the following two scenarios:

  • Retrieve a service by key, generally speaking a string key.
  • Create a factory of an open generic type, like “IRepository<>”

 

The implementation is right here. The class you might be interested on is this one.

Ideas?

| More

I started to work in an HQL addin for Visual Studio two weeks ago. As described in the project site:

This Visual Studio addin will provide the following features for the HQL file extension:
-syntax highlighting (done),
-syntax checking (done)
-intellisense (not yet)

Currently the addin support syntax highlighting and checking as you can see in the following screenshot:

2010-07-25_1011

One of the more interesting part of this, is that I have not implemented a parser or anything. I have only used the lexer and the parser inside NHibernate 3, so these features will be up to date always. In fact you can see the error “No viable alternative” that is common for most of the ANTLR parsers.

My idea is to support Intellisense as well, so I have reached Felice Pollano. He already has done a lot of work for other application named NHWorkBench and we are willing to cooperate for the intellisense part.

There is a step by step guid on how to use “hql” files with nhibernate here.

I have published an alpha release in the Visual Studio Online Gallery, so is very easy to install it:

2010-07-27_0845

If you are doing HQL have a look to my pluggin and let me know your comments!

| More

In a previous article I talked about an event publisher based on Reactive Extensions, and I wrote some examples of subscriptors based on IObservable.

I will talk about two different kind of subscriptors or observers in this post.

I am using this pattern in my presenters (user interface), so I will start this post with a simple example of use case.

The first interface is the “Albums Browser”:

myImage

And the second interface is the “Album Editor”:

myImage (1)

 

So, I have two concerns in this scenario:

  • I want to update the Browser when the user saves a change on an album.
  • I want to open the edit use case when the user press the button Edit. But I don’t want a hard reference to the Edit Album Presenter or window, in the browser.

So, I will declare two events:

public class AlbumUpdated
{
    public AlbumUpdated(int id)
    {    
        AlbumId = id;
    }

    //Poid of the album
    private object AlbumId{get; private set;}
}


public class AlbumEditRequest
{
    public AlbumUpdated(int id)
    {    
        AlbumId = id;
    }

    //Poid of the album
    private object AlbumId{get; private set;}
}

The command to raise the event is the same in both cases:

EventAggregator.Publish(new AlbumUpdated(id));

EventAggregator.Publish(new AlbumEditRequest(SelectedAlbum.Id));

But we need two kind of subscription mechanism.

Instance Subscription

The observers for AlbumUpdated are live object instances watching the event. So the browser for that matter look like this:

public class AlbumBrowserPresenter
{
    public AlbumBrowserPresenter(
        EventAggregator eventAggregator)
    {
        eventAggregator.GetEvent<AlbumUpdated>()
                    .Subscribe(ReloadGrid);
    }
    
    private void ReloadGrid()
    {
        //do the reload here.
    }   
}

And you can subscribe to this same event in other use cases, for instance when you have a selector for Albums.

Type Subscription

The observer of AlbumEditRequest is a type, this means that the handler of this event is not a live object. The event aggregator implementation “create” an instance of all types implementing the interface and then call an specific method. The edit presenter looks like this:

public class AlbumEditPresenter
  : IHandler<AlbumEditRequest>
{
    public void Handle(AlbumEditRequest @event)
    {
        InitWithId(@event.AlbumId);
    }

    //...
}

The easy way to handle this scenario in the event aggregator is something like this:

public void Publish<TEvent>(TEvent @event)
{
    object subject;

    if (subjects.TryGetValue(typeof(TEvent), out subject))
    {
        ((ISubject<TEvent>)subject)
            .OnNext(sampleEvent);
    }

    ServiceLocator.Current
                .GetAllInstances<IHandler<TEvent>>()
                .ForEach(h => h.Handle(@event));
}

This same code is used in many places and examples for Domain Events, but we use it here with other purpose.

| More

Luego de haber creado el script, como explique anteriormente en la Parte 1 de esta serie, lo que vamos a hacer es añadir nuestro proyecto a un servidor de integración continua. Para este ejemplo voy a utilizar TeamCity, aunque existen otros como CruiseControl, y el propio de TFS, Team Foundation Build.

TeamCity es por el momento mi preferido ya que su instalación es sencilla, su versión Profesional es gratuita y se integra muy bien con varias herramientas diferentes.

La instalación de TeamCity queda fuera del alcance de esta entrada, pero es muy sencilla. La única sugerencia sobre este punto es asignar una cuenta de correo, a la aplicación para que pueda comunicarnos cuando “metemos la pata”.

Crear un proyecto

2010-06-21_1726

Nada complicado, lo único que tenemos que hacer aquí es asignarle un nombre y una descripción a nuestro proyecto.

Configurar la conexión al servidor de control de versiones

2010-06-21_1729

Este paso es muy sencillo, aquí le diremos a TeamCity donde esta alojado el proyecto. Para este caso he seleccionado Subversion como control de versiones. Lo próximo que debo decirle es el url del proyecto, un nombre de usuario y contraseña. Luego hay muchas más opciones para configurar, pero los valores que vienen por defecto suelen ser los correctos.

Al final de esta página hay un botón para probar si los datos de conexión son válidos.

Crear una configuración para la generación

A continuación en la solapa “General” de la administración de nuestro proyecto debemos seleccionar la opción “Create Build Configuration”.

El proceso implica una serie de pasos, de los cuales los más importantes son el 2do y el 3ro:

2010-06-21_1736

En el segundo paso lo único que debemos hacer, es seleccionar el VCS root que creamos anteriormente.

A continuación, en el tercer paso, debemos configurar nuestro “Runner” acorde al script de generación que cree en mi post anterior, tal como sigue:

2010-06-21_1740

Build Runner; selccionamos MsBuild, ya que es la plataforma sobre la cual escribimos el script.

Build file path; nuestro xml de entrada, el nombre que le dimos en el post anterior fue default.build.

Luego lo más importante en esta página es la última configuración, que le dice a TeamCity que tiene que importar reportes de NUnit desde el path “$(OutputPath)\Reports\*.xml”.

Y esto es básicamente todo lo que hay que hacer para tener nuestro proyecto bajo integración continua. Los demás pasos tienen opciones por defecto que para proyectos simples son suficientes, y a medida que vayamos necesitando mas cosas como dependencias entre distintos proyectos dentro de nuestro proceso, podremos ir configurando.

| More