zondag 10 maart 2013

Fluent Factory Method with Lambda's

In a previous article I showed you the Fluent Interface / Fluent Builder pattern. If you want to build a nice factory method you can use that pattern. But there's another option; factory with lambda expressions. then you can wrtite a factory method that you can use like this:


var validator = ValidatorFactory.New(config =>
      {
         config.HasName("Test");
         config.UseThatValidator();
       });

validator.Validate();


How does it work?

In this example we have two validators that implement the IValidator interface:



public interface IValidator
{
   void Validate();
}


public class ThisValidator : IValidator
{
   private string _name;

   public void Validate()
   {
      // Do something
   }
}


public class ThatValidator : IValidator
{
   private string _name;

   public void Validate()
   {
      // Do something
   }
}


Next we need a Configurator that can be used the the factory later:



public class ValidatorConfigurator
{
}

As you can see ThisValidator and ThatValidator have a name, so we need to have a way to configure that name. Let's add a method to the ValidatorConfigurator to set the name:



public class ValidatorConfigurator
{
   internal string _name;


   public ValidatorConfigurator HasName(string name)
   {
      _name = name;
      return this;
   }

}


This is the factory that we'll be using:



public static class ValidatorFactory

{
   public static IValidator New()
   {
   }
}




At this stage we can only call the New() method of the factory:

var validator = ValidatorFactory.New();



Add a lambda expression

We can't write a lambda expression as parameter of the New() method. How do we fix that? The easiest way is to add an Action with the Configuration as type:


public static class ValidatorFactory

{
   public static IValidator New(Action<ValidatorConfigurator> applySettings)
   {
   }
}



And this is what we can do with the factory now:

var validator = ValidatorFactory.New(x=>x.HasName("BestValidatorEver"));



Create a validator in the Factory

The New() method of the factory does nothing now. So we won't get a valid Validator back. Let's add some code to the New() method:


public static class ValidatorFactory

{
   public static IValidator New(Action<ValidatorConfigurator> applySettings)
   {
      // We need to have an instance of ValidatorConfigurator
      var validatorConfigurator = new ValidatorConfigurator();

      // Apply the settings to the instance of ValidatorConfigurator
      applyConfiguration(validatorConfigurator);

      // Let the Configurator create a Validator
      return validatorConfigurator.CreateValidator();
   }
}





Create a validator in the Configurator

In the factory above the Create() method of the ValidatorConfigurator was called. Let's write the code for that method:


internal IValidator CreateValidator()
{
   IValidator validator = new ThisValidator();
   validator.Name = this._name;

   return validator;
}



Conclusion

If we run this code:

var validator = ValidatorFactory.New(x=>x.HasName("BestValidatorEver"));

We get an instance of ThisValidator with the name BestValidatorEver. It's obvious that we need to expand the code so that you can choose between ThisValidator or ThatValidator. But that isn't to hard now, right?


donderdag 7 maart 2013

Building Windows Services using Autofac

In the previous article I've shown how you can build a Windows Service in .Net using Topshelf. In this article I will show how you can use Autofac in a Windows Service with Topshelf.

We ended the previous article with this little Windows Service:




Currently MyService is doing two things

1. looping till the Windows Service stops
2. Execute some work in the DoWork() method.

I don't think number two belongs in MyService. It violates the Single Responsibility Principle and as it's a private method, so we can't easily unit test it. The solution is to create a new class named Worker, and put all the work there:





Let's write the code for Worker:


public class Worker
{
   private Guid _workerId;

   public Worker()
   {
      _workerId = Guid.NewGuid();
   }

   public void Work()
   {
      Console.WriteLine("I am working. My id is {0}.", _workerId);

      Console.WriteLine("  Step 1");
     System.Threading.Thread.Sleep(1000);

     Console.WriteLine("  Step 2");
     System.Threading.Thread.Sleep(1000);

     Console.WriteLine("  Step 3");
     System.Threading.Thread.Sleep(1000);

     Console.WriteLine("  Step 4");
     System.Threading.Thread.Sleep(1000);

     Console.WriteLine("  Step 5");
     System.Threading.Thread.Sleep(1000);
   }
}


Now we can use Worker in MyService like this:


public class MyService
{
   readonly CancellationTokenSource _cancellationTokenSource;
   readonly CancellationToken _cancellationToken;
   readonly Task _task;

        public  MyService()
        {
            _cancellationTokenSource = new CancellationTokenSource();
            _cancellationToken = _cancellationTokenSource.Token;
            _task = new Task(DoWork, _cancellationToken);
        }

        private void DoWork()
        {
            while (!_cancellationTokenSource.IsCancellationRequested)
            {
                new Worker.Work();
            }
        }

        public void Start()
        {
            _task.Start();
        }

        public void Stop()
        {
            _cancellationTokenSource.Cancel();
            _task.Wait();
        }
    }


When we run the app we will get this output:


Configuration Result:
[Success] Name MyService
[Success] Description MyService using Topshelf
[Success] ServiceName MyService
Topshelf v3.1.106.0, .NET Framework v4.0.30319.18033
The MyService service is now running, press Control+C to exit.
I am working. My id is 7b60edb6-1d44-4750-81de-09468daeaecb.
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5
I am working. My id is 37c0e8bb-2f46-4dc7-8568-dac6b5f5e0eb.
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5
I am working. My id is e1413c84-0c18-4682-b56a-7a94365d2b57.
  Step 1
  Step 2
   ...


Notice that the Worker gets a new id everytime.

At this moment the Worker doesn't have any dependencies. In the real world the Worker maybe needs Entity Framework, Log4Net, or has to call a WCF service. We can instanciate all these dependencies by hand in the while-loop, and but I like to use autofac to do this for me.


Autofac and Windows Services

Where are we going to initialize autofac? In the Main() method of Program:




Let's install the Autofac nuget package:




Now we can initialise Autofac in the Main() method of Program. First add a new using statement:

using Autofac;

Next add the following code to the top of the Main() method::


var builder = new Autofac.ContainerBuilder();
builder.RegisterType<MyService>();
var container = builder.Build();


We can now use the Autofac container to get an instance of MyService and let it run in Topshelf. This is the old code:


HostFactory.Run(hostConfigurator =>
{
   hostConfigurator.Service<MyService>(serviceConfigurator =>
   {
      serviceConfigurator.ConstructUsing(() => new MyService());
      serviceConfigurator.WhenStarted(myService => myService.Start());
      serviceConfigurator.WhenStopped(myService => myService.Stop());
   });

   hostConfigurator.RunAsLocalSystem();
   hostConfigurator.SetDescription("MyService using Topshelf");
   hostConfigurator.SetDisplayName("MyService");
   hostConfigurator.SetServiceName("MyService");
});


Replace the marked line with this line:

serviceConfigurator.ConstructUsing(() => container.Resolve<MyService>());

If we run the app again, we will get the same results as previously, but now MyService is instanciated by Autofac.



Inject the Worker

Now we are using Autofac the create an instance of MyService. So how about an instance of Worker?
This is a but trickier. Let me start by showing the way it won't work right. Then you'll get a clue about how to do it the right way.

Register the Worker with Autofac:


var builder = new Autofac.ContainerBuilder();
builder.RegisterType<MyService>();
builder.RegisterType<Worker>();
var container = builder.Build();


We can inject Worker in the constructor of MyService:


public class MyService
{
   readonly CancellationTokenSource _cancellationTokenSource;
   readonly CancellationToken _cancellationToken;
   readonly Task _task;
   readonly Worker _worker;

   public MyService(Worker worker)
   {
      _worker = worker;

      _cancellationTokenSource = new CancellationTokenSource();
      _cancellationToken = _cancellationTokenSource.Token;

      _task = new Task(DoWork, _cancellationToken);
   }
   . . .
}


And then use _worker in the DoWork() method:


private void DoWork()
{
   while (!_cancellationTokenSource.IsCancellationRequested)
   {
      _worker.Work();
   }
}



This is what we'll see when we run the app again:

Configuration Result:
[Success] Name MyService
[Success] Description MyService using Topshelf
[Success] ServiceName MyService
Topshelf v3.1.106.0, .NET Framework v4.0.30319.18033
The MyService service is now running, press Control+C to exit.
I am working. My id is 08f6cc4a-e843-4d3d-a5c3-affeab56e0cf.
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5
I am working. My id is 08f6cc4a-e843-4d3d-a5c3-affeab56e0cf.
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5

I am working. My id is 08f6cc4a-e843-4d3d-a5c3-affeab56e0cf.
  Step 1


Notice that the Worker has the same id everytime. This is not the same as before, when we got a new id everytime.

The problem here is that Worker only gets injected once, and that instance is used everytime. But I want to get a new Worker everytime. How do we do that? We need to manage the lifetime of the components a bit better. (You can read more about that here and here)



LifetimeScope

We can tell Autofac that we want a new instance of Worker. We do this by creating a new Autofac LifetimeScope, and resolving a Worker from it. We have to change only a small bit of code for this to work. Let's start with the constructor of MyService:



public class MyService
{
   readonly CancellationTokenSource _cancellationTokenSource;

   readonly CancellationToken _cancellationToken;
   readonly Task _task;

   readonly ILifetimeScope _lifetimescope;

   public MyService(ILifetimeScope lifetimescope)
   {
      _lifetimescope = lifetimescope;

      _cancellationTokenSource = new CancellationTokenSource();
      _cancellationToken = _cancellationTokenSource.Token;

      _task = new Task(DoWork, _cancellationToken);
     }

   . . .
}

We can use the lifetimescope in the DoWork() method:


private void DoWork()
{
   while (!_cancellationTokenSource.IsCancellationRequested)
   {
      using(var workerScope = _lifetimescope.BeginLifetimeScope())
      {
         var worker = workerScope.Resolve<Worker>();
         worker.Work();
      }
   }
}

When we run the app now, we'll see that we get a new worker everytime again:

Configuration Result:

[Success] Name MyService
[Success] Description MyService using Topshelf
[Success] ServiceName MyService
Topshelf v3.1.106.0, .NET Framework v4.0.30319.18033
The MyService service is now running, press Control+C to exit.
I am working. My id is 4b7fb6b3-3222-4023-9452-790ff7feb49c.
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5
I am working. My id is 02cb1bcd-64ca-417f-8d2b-f1afdeef75d6.
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5
I am working. My id is 6da61ae3-8d50-4361-b0aa-4b77823c35b3.
  Step 1



Without ILifetimescope

We can make it even nicer by using a factory. Autofac can create factories out of the box for us.  You can read more about that here.

It works like this:

Change the constructor of MyService to accept an Autofac factory for Worker:




public class MyService
{
   readonly CancellationTokenSource _cancellationTokenSource;


   readonly CancellationToken _cancellationToken;
   readonly Task _task;


   readonly Func<Owned<Worker>> _workerFactory;

   public MyService(Func<Owned<Worker>> workerFactory)
   {
      _workerFactory = workerFactory;

      _cancellationTokenSource = new CancellationTokenSource();

      _cancellationToken = _cancellationTokenSource.Token;

      _task = new Task(DoWork, _cancellationToken);

   }
   . . .
}


We can use the _workerFactory in the DoWork() method:


private void DoWork()
{
   while (!_cancellationTokenSource.IsCancellationRequested)
   {
      using(var workerFactory = _workerFactory())
      {
         var worker = workerFactory.Value;
         worker.Work();
      }
   }
}





As you can see we never have to change anything in the registration with Autofac. We registered Worker once, and we can get an instance of Worker or a factory of Worker from Autofac if we want.
Also the lifetime and disposing is being managed by Autofac, which really makes it easy for us to focus in implementing the logic and not focus on the plumbing code.


woensdag 6 maart 2013

Building Windows Services with C# and Topshelf

The quickstart on the Topshelf site is only showing the real basics of getting a Windows Service up and running. There are a couple of importants details not touched, that I will write about in this blog.

Create a new Solution with the Console Application Template. Because Topshelf is doing the plumbing, we don't need to use the Windows Service template anymore.




If you're using Visual Studio 2010, don't forget to turn off Client Profile

When the solution is created it will look like this:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XmplWindowsService
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

The Main method is the entrypoint of the Windows Service. This is where we will setup Topshelf. But before we do that, we have to create a class that will do the actual work that will be done inside the Windows Service. So let's create a new class:

public class MyService
{
}

This class must have a Start() and a Stop() method:

public class MyService
{
   public void Start()
   {
   }

   public void Stop()
   {
   }
}


This is what we have so far:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XmplWindowsService
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }

    public class MyService
    {
        public void Start()
        {
        }

        public void Stop()
        {
        }
    }
}


Now we can install Topshelf into the project:




Let's setup Topshelf inside the Main method of the Console Application:


static void Main(string[] args)
{
   HostFactory.Run(hostConfigurator =>
   {
      hostConfigurator.Service<MyService>(serviceConfigurator =>
      {
         serviceConfigurator.ConstructUsing(() => new MyService());
         serviceConfigurator.WhenStarted(myService => myService.Start());
         serviceConfigurator.WhenStopped(myService => myService.Stop());
      });

      hostConfigurator.RunAsLocalSystem();

      hostConfigurator.SetDisplayName("MyService");
      hostConfigurator.SetDescription("MyService using Topshelf");
      hostConfigurator.SetServiceName("MyService");
   });
}


When we run the application, we will see this:


Configuration Result:
[Success] Name MyService
[Success] Description MyService using Topshelf
[Success] ServiceName MyService
Topshelf v3.1.106.0, .NET Framework v4.0.30319.18033
The MyService service is now running, press Control+C to exit.

It shows us its name, description and servicename, just like we configured. We can see the version numbers, and the last line tells us how the stop the Windows Service, when debugging or when it's running as console application. Offcourse we can't press Control+C to stop it when it's running as a Windows Service.

Now the MyService class isn't doing anything just yet. So now it's time to give MyService some work to do. Let's for example write something to screen every second:


public class MyService
{
   public void Start()
   {
      while (true)
      {
         Console.WriteLine("I am working");
         System.Threading.Thread.Sleep(1000);
      }
   }

   public void Stop()
   {
   }
}

When we start the app we will see it write "I am working" to the screen every second. However, when we press Control+C the application will not stop. Topshelf will try to stop MyService, but won't succeed since MyService is in a never ending while-loop.

So we have to have a signal to let the loop know when to stop. Therefore we add a boolean named doWork, and set it to true when we start the loop. The doWork boolean will be set to false when we press Control+C and Topshelf calls the Stop() method.


public class MyService
{
   private bool _doWork;

   public void Start()
   {
      _doWork = true;

      while (_doWork)
      {
         Console.WriteLine("I am working");
         System.Threading.Thread.Sleep(1000);
      }
   }

   public void Stop()
   {
      _doWork = false;
   }
}


When we start the debugger and press Control+C, the application will quit as it should.

Unfortunately the code is still nog perfect. Remember when we first started the application where MyService did nothing and Topshelf wrote this to the console:

Configuration Result:
[Success] Name MyService
[Success] Description MyService using Topshelf
[Success] ServiceName MyService
Topshelf v3.1.106.0, .NET Framework v4.0.30319.18033
The MyService service is now running, press Control+C to exit.


Now that MyService is running in a while loop, the last line is not printed anymore. Well actually it is printed after we stopped the service.


Configuration Result:
[Success] Name MyService
[Success] Description MyService using Topshelf
[Success] ServiceName MyService
Topshelf v3.1.106.0, .NET Framework v4.0.30319.18033
I am working
I am working
I am working
Control+C detected, attempting to stop service.
The MyService service is now running, press Control+C to exit.
The MyService service has stopped.

The message that the service is running, is printed after the Start() method of MyService returns, but that only happens when we stop the service. If we would use a Timer to do something every second it wouldn't be a problem, because a Timer is doing it's work asynchronously. And when we read messages from a queue async it wouldn't be a problem either. But I think it's good to show how we can make the Start() method in this example return immediately too.


System.Threading.Tasks

We are going to use the System.Threading.Tasks namespace to make MyService execute asynchronous work.

First let's move the content of the Start() method, to another method called DoWork():

private void DoWork()
{
   _doWork = true;

   while (_doWork)
   {
      Console.WriteLine("I am working");
      System.Threading.Thread.Sleep(1000);
   }
}

we are going to call the DoWork() method with a Task. Let's create this task in the constructor of MyService:


public class MyService
{
   bool _doWork;
   readonly Task _task;

   public MyService()
   {
      _task = new Task(DoWork);
   }

   ...
}

Now we can start this Task from the Start() method of MyService:


public void Start()
{
   _task.Start();
}


This is what MyService looks like now:


public class MyService
{
   bool _doWork;
   readonly Task _task;

   public MyService()
   {
      _task = new Task(DoWork);
   }

   public void Start()
   {
      _task.Start();
   }

   public void Stop()
   {
      _doWork = false;
   }

   private void DoWork()
   {
      _doWork = true;

      while (_doWork)
      {
         Console.WriteLine("I am working");
         System.Threading.Thread.Sleep(1000);
      }
   }
}


When we run the application, we will see this:


Configuration Result:
[Success] Name MyService
[Success] Description MyService using Topshelf
[Success] ServiceName MyService
Topshelf v3.1.106.0, .NET Framework v4.0.30319.18033
The MyService service is now running, press Control+C to exit.
I am working
I am working

Exactly what we want. The message that MyService is running is coming first, and then the "I am working" messages are written.

But it's still not completely right. Let me tell you why.


Quit before work is finished

The problem that we have now is that the Windows Service will quit if you press Control+C, but it doesn't take into account any work in progress. This can be demoed quite easily.

Add some more work to the DoWork() method:


private void DoWork()
{
   _doWork = true;

   while (_doWork)
   {
      Console.WriteLine("I am working");

      Console.WriteLine("   Step 1");
      System.Threading.Thread.Sleep(1000);

      Console.WriteLine("   Step 2");
      System.Threading.Thread.Sleep(1000);

      Console.WriteLine("   Step 3");
      System.Threading.Thread.Sleep(1000);

      Console.WriteLine("   Step 4");
      System.Threading.Thread.Sleep(1000);

      Console.WriteLine("   Step 5");
      System.Threading.Thread.Sleep(1000);
   }
}


If we run the application, and then press Control+C after step one, we can get output like this:

Configuration Result:

[Success] Name MyService
[Success] Description MyService using Topshelf
[Success] ServiceName MyService
Topshelf v3.1.106.0, .NET Framework v4.0.30319.18033
The MyService service is now running, press Control+C to exit.
I am working
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5
I am working
  Step 1
Control+C detected, attempting to stop service.
The MyService service has stopped.


The yellow marked lines are important. You can see that step 2, 3, 4 and 5 are not written, because the Service has stopped. However, I only want the service to be stopped when step 5 is finished. The best way to do this is remove the _doWork boolean, and use a Cancellationtoken.

Let's switch back to the constructor of MyService, and create a CancellationToken that we can use in the Task:

public class MyService
{
   readonly CancellationTokenSource _cancellationTokenSource;
   readonly CancellationToken _cancellationToken;
   readonly Task _task;

   public MyService()
   {
      _cancellationTokenSource = new CancellationTokenSource();
      _cancellationToken = _cancellationTokenSource.Token;

      _task = new Task(DoWork, _cancellationToken);
   }

   ...
}

Now we can use the CancellationTokenSource in the DoWork() method:

private void DoWork()
{
   while (!_cancellationTokenSource.IsCancellationRequested)
   {
      Console.WriteLine("I am working");

      Console.WriteLine("   Step 1");
      System.Threading.Thread.Sleep(1000);

      Console.WriteLine("   Step 2");
      System.Threading.Thread.Sleep(1000);

      Console.WriteLine("   Step 3");
      System.Threading.Thread.Sleep(1000);

      Console.WriteLine("   Step 4");
      System.Threading.Thread.Sleep(1000);

      Console.WriteLine("   Step 5");
      System.Threading.Thread.Sleep(1000);
   }
}

And we can cancel the Task in the Stop() method:

public void Stop()
{
   _cancellationTokenSource.Cancel();
   _task.Wait();
}

If we run the application, and then press Control+C after step one, we get exactly what we want:

Configuration Result:
[Success] Name MyService
[Success] Description MyService using Topshelf
[Success] ServiceName MyService
Topshelf v3.1.106.0, .NET Framework v4.0.30319.18033
The MyService service is now running, press Control+C to exit.
I am working
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5
I am working
  Step 1
Control+C detected, attempting to stop service.
  Step 2
  Step 3
  Step 4
  Step 5
The MyService service has stopped.


Conclusion

In this blog I've shown how easy it is to create a Windows Service in C# and the Topshelf nuget package. I've also shown how you can use a Task to start an asynchronous proces to do some work, and how the task can be stopped in a clean way, without leaving partial executed work behind.