Sometimes you want to set a specific CultureInfo, do something and afterwards reset to the original CultureInfo. We wanted to do that when rendering a pdf, which had to work with dates in the correct format.
So what we did was this:
var originalCultureInfo = Thread.CurrentThread.CurrentCulture;
var culture = new CultureInfo("fr-FR");
Thread.CurrentThread.CurrentCulture = culture;
RenderPdf();
Thread.CurrentThread.CurrentCulture = originalCultureInfo;
But that can be made a lot simpler, with less risk of forgetting to reset the CurrentCulture on the last line:
using (new CustomCulture("fr-FR"))
{
RenderPdf();
}
The key is writing a CustomCulture class that inherits from IDisposable:
public class CustomCulture : IDisposable
{
readonly CultureInfo _originalCultureInfo;
public CustomCulture(string name)
{
_originalCultureInfo = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo(name);
}
public void Dispose()
{
Thread.CurrentThread.CurrentCulture = _originalCultureInfo;
}
}
vrijdag 21 augustus 2015
donderdag 7 mei 2015
Bookmarks
Best practices
- Order of items in classes: Fields, Properties, Constructors, Methods http://stackoverflow.com/a/310967/369117
- Guidelines for Collections https://msdn.microsoft.com/en-us/library/dn169389
maandag 20 april 2015
Technical stories on the backlog
How can you add technical stories to the backlog when the product owner wants every story to have business value? Let's take the following titles as an example:
Connect the monitoring system to ServiceX.
Use the configuration system and not the web.config for settings of ServiceX.
As a developer these titles are perfectly fine. As a product owner the titles are too technical. One solution is to rewrite the titles in the following way:
As operations staff I want to monitor aspect A of ServiceX.
As operations staff I want to configure ServiceX with the configuration system.
woensdag 30 juli 2014
Authenticate Json Web Token in ASP.Net Web API
public class JwtMessageHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var authorizationParameter = request.Headers.Authorization.Parameter;
var handler = new JwtSecurityTokenHandler();
var x509Certificate2 = new X509Certificate2(@"c:\temp\ADFS Signing.cer");
var x509SecurityToken = new X509SecurityToken(x509Certificate2);
var tokenValidationParameters = new TokenValidationParameters
{
SigningToken = x509SecurityToken,
AllowedAudience = "[relyingparty identifier]",
ValidIssuer = "[Federation Service identifier]"
};
ClaimsPrincipal res;
res = handler.ValidateToken(authorizationParameter,
tokenValidationParameters);
HttpContext.Current.User = res;
Thread.CurrentPrincipal = res;
return base.SendAsync(request, cancellationToken);
}
}
The JwtMesssageHandler can be configured in the global.asax:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// other configuration
GlobalConfiguration.Configuration.MessageHandlers.Add(new JwtMessageHandler());
}
}
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var authorizationParameter = request.Headers.Authorization.Parameter;
var handler = new JwtSecurityTokenHandler();
var x509Certificate2 = new X509Certificate2(@"c:\temp\ADFS Signing.cer");
var x509SecurityToken = new X509SecurityToken(x509Certificate2);
var tokenValidationParameters = new TokenValidationParameters
{
SigningToken = x509SecurityToken,
AllowedAudience = "[relyingparty identifier]",
ValidIssuer = "[Federation Service identifier]"
};
ClaimsPrincipal res;
res = handler.ValidateToken(authorizationParameter,
tokenValidationParameters);
HttpContext.Current.User = res;
Thread.CurrentPrincipal = res;
return base.SendAsync(request, cancellationToken);
}
}
The JwtMesssageHandler can be configured in the global.asax:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// other configuration
GlobalConfiguration.Configuration.MessageHandlers.Add(new JwtMessageHandler());
}
}
maandag 24 februari 2014
zondag 23 februari 2014
Asynchronous Programming Model
This is a good explanation of how to make asynchronous calls with the Asynchronous Programming Model ( begin/end):
Calling Synchronous Methods Asynchronously
Calling Synchronous Methods Asynchronously
maandag 27 januari 2014
Competing consumers and returning results with in-memory-queues (BlockingCollection)
I needed a way to to put some work in a queue, consume it and return the result to the producer of the work. In C# we can use the BlockingCollection class and TaskCompletionSource for that.
The code in this blogpost is based on the code from Albahari.What I want to do is this create a Producer which creates work and places that on a queue. I'll also want to create Consumers which take work off the queue and send the result back to the Producer when they are done. See the following image for an overview:
Let's start with a simple console application:
(Don't forget to set it to the correct framework, as VS 2010 defaults to client framework 4.0)
class Program
{
static void Main()
{
// Put something on a queue
}
}
This is the class that we are going to put on the queue:
public class WorkItem
{
public readonly TaskCompletionSource<int> TaskSource;
public readonly int Context;
public readonly CancellationToken? CancelToken;
public WorkItem(
TaskCompletionSource<int> taskSource,
int context,
CancellationToken? cancelToken)
{
TaskSource = taskSource;
Context = context;
CancelToken = cancelToken;
}
}
Next we create the queue we are going to use for enqueueing the work:
public class ProducerConsumerQueue : IDisposable
{
readonly BlockingCollection<WorkItem> _workitemQueue =
new BlockingCollection<WorkItem>();
public Task<int> EnqueueTask(int context)
{
return EnqueueTask(context, null);
}
public Task<int> EnqueueTask(int context,
CancellationToken? cancelToken)
{
var tcs = new TaskCompletionSource<int>();
_workitemQueue.Add(new WorkItem(tcs, context, cancelToken));
return tcs.Task;
}
public void Dispose()
{
_workitemQueue.CompleteAdding();
}
}
As you can see our ProducerConsumerQueue uses a BlockingCollection internally. This is a great class that let's multiple consumers/workers read from it in a thread-safe manner.
Next, create the consumer:
public class Consumer
{
private readonly BlockingCollection<WorkItem> _workitemQueue;
public Consumer(BlockingCollection<WorkItem> workitemQueue)
{
_workitemQueue = workitemQueue;
}
public void Consume()
{
foreach (WorkItem workItem in _workitemQueue.GetConsumingEnumerable())
{
if (workItem.CancelToken.HasValue &&
workItem.CancelToken.Value.IsCancellationRequested)
{
workItem.TaskSource.SetCanceled();
}
else
{
try
{
Thread.Sleep(1000); // simulate work
workItem.TaskSource.SetResult(workItem.Context + 1);
}
catch (OperationCanceledException ex)
{
if (ex.CancellationToken == workItem.CancelToken)
{
workItem.TaskSource.SetCanceled();
}
else
{
workItem.TaskSource.SetException(ex);
}
}
catch (Exception ex)
{
workItem.TaskSource.SetException(ex);
}
}
}
}
}
So how do we start the consumers?
We do that in the constructor of the ProducerConsumerQueue:
public ProducerConsumerQueue(int workerCount)
{
for (int i = 0; i < workerCount; i++)
{
var consumer = new Consumer(_workitemQueue);
Task.Factory.StartNew(consumer.Consume);
}
}
Finally we can finish the console application:
class Program
{
static void Main()
{
var producerConsumerQueue = new ProducerConsumerQueue(2);
Task<int> task1 = producerConsumerQueue.EnqueueTask(1);
Task<int> task2 = producerConsumerQueue.EnqueueTask(2);
Task<int> task3 = producerConsumerQueue.EnqueueTask(3);
Console.WriteLine(task1.Result);
Console.WriteLine(task2.Result);
Console.WriteLine(task3.Result);
Console.ReadLine();
}
}
If we run this, we will start three tasks. Each task will get an input value, add one to it, and return the value to the console app. WE start with two consumers, so after one second the first two tasks finish and the following output is printed:
2
3
A second later the third task finished, and we will see this:
4
You can play around with the number of consumers and the number of enqueued WorkItems.
maandag 13 januari 2014
Design Patterns Quick Reference
Jason McDonald made a Quick Reference for Design Patterns. You can get it here:
http://www.mcdonaldland.info/2007/11/28/40/
http://www.mcdonaldland.info/2007/11/28/40/
woensdag 31 juli 2013
Call WCF service with ADFS token
How can we configure a WCF client to call an ADFS-secured WCF service? In this blog I'll show you how to do it with code only, no xml-configuration needed.
The are only two steps to take:
1. Get a securityToken from ADFS
2. Create a WCF channel to the WCF service, using the securityToken.
internal class Program
{
private static void Main()
{
var stsEndpoint =
"https://myAdfsServer/adfs/services/trust/13/certificatemixed";
var clientCertificateThumbprint = "[put the thumbprint here]";
var svcEndpoint = "https://myDomain/myService.svc";
var token = GetToken(stsEndpoint, svcEndpoint);
var channel = CreateChannel<IMyService>(token,
svcEndpoint,
clientCertificateThumbprint);
channel.Foo();
}
}
private static SecurityToken GetToken(string stsEndpoint,
string svcEndpoint,
string thumbprint)
{
var binding = new
CertificateWSTrustBinding(SecurityMode.TransportWithMessageCredential);
var factory = new WSTrustChannelFactory(binding, stsEndpoint)
{
TrustVersion = TrustVersion.WSTrust13
};
factory.Credentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindByThumbprint,
thumbprint);
var rst = new RequestSecurityToken
{
RequestType = WSTrust13Constants.RequestTypes.Issue,
AppliesTo = new EndpointAddress(svcEndpoint),
KeyType = WSTrust13Constants.KeyTypes.Symmetric
};
var channel = factory.CreateChannel();
var token = channel.Issue(rst);
return token;
}
The are only two steps to take:
1. Get a securityToken from ADFS
2. Create a WCF channel to the WCF service, using the securityToken.
Create the WCF client
To get started, let's create a console application that will be the client:internal class Program
{
private static void Main()
{
var stsEndpoint =
"https://myAdfsServer/adfs/services/trust/13/certificatemixed";
var clientCertificateThumbprint = "[put the thumbprint here]";
var svcEndpoint = "https://myDomain/myService.svc";
var token = GetToken(stsEndpoint, svcEndpoint);
var channel = CreateChannel<IMyService>(token,
svcEndpoint,
clientCertificateThumbprint);
channel.Foo();
}
}
How to get a secured token from ADFS?
The GetToken() method looks like this:private static SecurityToken GetToken(string stsEndpoint,
string svcEndpoint,
string thumbprint)
{
var binding = new
CertificateWSTrustBinding(SecurityMode.TransportWithMessageCredential);
var factory = new WSTrustChannelFactory(binding, stsEndpoint)
{
TrustVersion = TrustVersion.WSTrust13
};
factory.Credentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindByThumbprint,
thumbprint);
var rst = new RequestSecurityToken
{
RequestType = WSTrust13Constants.RequestTypes.Issue,
AppliesTo = new EndpointAddress(svcEndpoint),
KeyType = WSTrust13Constants.KeyTypes.Symmetric
};
var channel = factory.CreateChannel();
var token = channel.Issue(rst);
return token;
}
Please note that I'm using a client certificate, and not Username/Password to authenticate.
With the token, the secured channel can be created, like this:
private static T CreateChannel<T>(SecurityToken token, string svcEndpoint) where T : class
{
var binding = new WS2007FederationHttpBinding(
WSFederationHttpSecurityMode.TransportWithMessageCredential
);
binding.Security.Message.EstablishSecurityContext = true;
binding.Security.Message.IssuedKeyType = SecurityKeyType.SymmetricKey;
var factory = new ChannelFactory<T>(binding, svcEndpoint);
factory.ConfigureChannelFactory();
// Turn Cardspace off
factory.Credentials.SupportInteractive = false;
var channel = factory.CreateChannelWithIssuedToken(token);
return channel;
}
vrijdag 26 april 2013
IoC containers compared
There are quite a few different IoC containers for .Net. How does one decide which IoC container to use? There are performance comparisons made, but as even the slowest IoC container only takes 0.04 milliseconds to resolve a dependency, performance is not a good discriminator.
I've decided to do a feature comparisons of Autofac, Structuremap and Unity. The results can be read below.
{
x.For<ISomethingService>()
.Use<SomethingService>();
}
builder.RegisterType<SomethingService>()
.As<ISomethingService>();
container.RegisterType<ISomethingService, SomethingService>();
builder.RegisterType<ThatService>()
.As<IThatService>()
.SingleInstance();
container.RegisterType<IThatService, ThatService>(
new ContainerControlledLifetimeManager());
Personally I don't like the term ContainerControlledLifetimeManager. Structuremap and Autofac have more obvious terms (Singleton and SingleInstance).
ObjectFactory.Initialize(x =>
{
x.Scan(a =>
{
a.Assembly("[AssemblyName]");
a.WithDefaultConventions();
});
}
Structuremap can autoscan assemblies, but you can't set any lifetimeoptions. If you want to do that, you have to write some custom code.
builder.RegisterAssemblyTypes(Assembly.Load("[AssemblyName]"))
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces()
.SingleInstance();
Autofac has the option to set lifetimeoptions. In the example above all repositories are registered as singletons (SingleInstance).
As far as I know, Unity doesn't provide a way to autoscan assemblies out of the box.
With Unity you can autoregister assemblies by using Unity Auto Registration. (Thanks to Björn Bailleul for letting me know).
{
public UnitOfWorkRegistry()
{
For<IUnitOfWork>().Singleton().Use<UnitOfWork>();
}
}
ObjectFactory.Initialize(x =>
{
x.AddRegistry<UnitOfWorkRegistry>();
}
Structuremap doesn't have a way to set any properties or pass constructor variables to the Registry.
The current version 2.5.2 was released in January 2009, with a 2.6 release scheduled for no later than the end of January 2009.
At the moment of writing this blog the current version of Structuremap is 2.6.4.1 and updated on august 13, 2012. But there are more problematic errors, like the quickstart, which says you can use the next statement to register a type:
x.ForRequestedType<IValidator>()
.TheDefaultIsConcreteType<Validator>();
And indeed you can, but the ForRequestedType and TheDefaultIsConcreteType are deprecated, so they shouldn't be on the quickstart anymore.
Another major gap in the documentation is that there's no information about ASP.Net MVC integration on the Structuremap homepage.
1. Go to the Unity homepage (http://unity.codeplex.com/)
2. Click on the Documentation tab (http://unity.codeplex.com/documentation)
3. Click on the link to MSDN (http://msdn.microsoft.com/en-us/library/ff647202)
4. Click on the link to Unity 3 (http://msdn.microsoft.com/en-us/library/dn170416.aspx)
5. I've found only a link to a guide that can be downloaded, not what I was looking for.
6. Click on the link to Unity 2.0 (http://msdn.microsoft.com/en-us/library/ff663144.aspx)
7. Found the online info about configuring Unity (http://msdn.microsoft.com/en-us/library/ff660846(v=pandp.20).aspx)
The online documentation itself is extensive and tedious. I find it diffucult to navigate. For example the text about MVC integration is nowhere to be found.
The PDF that can be downloaded looks a lot more inviting than the online documentation.
I've decided to do a feature comparisons of Autofac, Structuremap and Unity. The results can be read below.
Basic registration
Basic registration is easy in each of the frameworks.
Structuremap
ObjectFactory.Initialize(x =>{
x.For<ISomethingService>()
.Use<SomethingService>();
}
Autofac
var builder = new ContainerBuilder();builder.RegisterType<SomethingService>()
.As<ISomethingService>();
Unity
IUnityContainer container = new UnityContainer();container.RegisterType<ISomethingService, SomethingService>();
Registration of a singleton
Setting lifetimescope options like "singleton" are easy in each of the frameworks.Structuremap
ObjectFactory.Initialize(x =>
{
x.For<IThatService>()
.Singleton()
.Use<ThatService>();
}
{
x.For<IThatService>()
.Singleton()
.Use<ThatService>();
}
Autofac
var builder = new ContainerBuilder();builder.RegisterType<ThatService>()
.As<IThatService>()
.SingleInstance();
Unity
IUnityContainer container = new UnityContainer();container.RegisterType<IThatService, ThatService>(
new ContainerControlledLifetimeManager());
Personally I don't like the term ContainerControlledLifetimeManager. Structuremap and Autofac have more obvious terms (Singleton and SingleInstance).
Autoscanning assemblies
Some frameworks provide ways to automatically register all or specific classes from an assembly. This can really be helpfull if for example you want to register all repositories in your solution and you don't want to write every registration by hand.Structuremap
{
x.Scan(a =>
{
a.Assembly("[AssemblyName]");
a.WithDefaultConventions();
});
}
Structuremap can autoscan assemblies, but you can't set any lifetimeoptions. If you want to do that, you have to write some custom code.
Autofac
var builder = new ContainerBuilder();builder.RegisterAssemblyTypes(Assembly.Load("[AssemblyName]"))
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces()
.SingleInstance();
Autofac has the option to set lifetimeoptions. In the example above all repositories are registered as singletons (SingleInstance).
Unity
With Unity you can autoregister assemblies by using Unity Auto Registration. (Thanks to Björn Bailleul for letting me know).
Organizing registrations
In real-life you want to organize the registrations and not put everything in the global.asax.
Structuremap
public class UnitOfWorkRegistry : Registry{
public UnitOfWorkRegistry()
{
For<IUnitOfWork>().Singleton().Use<UnitOfWork>();
}
}
ObjectFactory.Initialize(x =>
{
x.AddRegistry<UnitOfWorkRegistry>();
}
Structuremap doesn't have a way to set any properties or pass constructor variables to the Registry.
Autofac
public class MyModule : Autofac.Module
{
public bool RandomProperty { get; set; }
protected override void Load(ContainerBuilder builder)
{
if (RandomProperty)
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().SingleInstance();
}
}
builder.RegisterModule(new MyModule() { RandomProperty = true });
Unity
I didn't find a way to use modules or registries with Unity. If anyone knows how to do this, please let me know.Documentation
Structuremap
The documentation of Structuremap is incomplete and outdated. For example the next text can be seen on the homepage of structuremap:
x.ForRequestedType<IValidator>()
.TheDefaultIsConcreteType<Validator>();
And indeed you can, but the ForRequestedType and TheDefaultIsConcreteType are deprecated, so they shouldn't be on the quickstart anymore.
Another major gap in the documentation is that there's no information about ASP.Net MVC integration on the Structuremap homepage.
Autofac
I have no criticism on the Autofac documentation. It is frequently updated (last update was 59 minutes ago since writing this text), and it's extensive. The most important chapters are easy to be found on the wiki on the Autofac homepage.Unity
I find it difficult to find the documentation on Unity. This is the path I had to follow for the online documentation:1. Go to the Unity homepage (http://unity.codeplex.com/)
2. Click on the Documentation tab (http://unity.codeplex.com/documentation)
3. Click on the link to MSDN (http://msdn.microsoft.com/en-us/library/ff647202)
4. Click on the link to Unity 3 (http://msdn.microsoft.com/en-us/library/dn170416.aspx)
5. I've found only a link to a guide that can be downloaded, not what I was looking for.
6. Click on the link to Unity 2.0 (http://msdn.microsoft.com/en-us/library/ff663144.aspx)
7. Found the online info about configuring Unity (http://msdn.microsoft.com/en-us/library/ff660846(v=pandp.20).aspx)
The online documentation itself is extensive and tedious. I find it diffucult to navigate. For example the text about MVC integration is nowhere to be found.
The PDF that can be downloaded looks a lot more inviting than the online documentation.
Final verdict
Autofac has the most extensive featureset when it comes to registration of classes. The documentation is up to date and easy to read.
Structuremap does a pretty good job too, but lacks in autoscanning features. The documentation is outdated.
Unity doesn't provide a way to autoscan assemblies, which leads to writing a lot of code yourself if you need that. (corrected by remark of Björn Bailleul) I didn't find a way to organize the registrations like the way it can be done with Autofac or Structuremap. The documentation is hard to find and difficult to navigate.
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();
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
}
}
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();
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"));
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();
}
}
internal IValidator CreateValidator()
{
IValidator validator = new ThisValidator();
validator.Name = this._name;
return validator;
}
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?
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.
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.
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)
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
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.
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.
Labels:
.net,
autofac,
C#,
Topshelf,
Windows Service
Abonneren op:
Posts (Atom)




