Here’s a super quick little powershell snippet to strip regions out of all C# files in a directory tree. Useful for legacy code where people hide long blocks in regions rather than encapsulate it into smaller methods/objects.
dir -recurse -filter *.cs $src | foreach ($_) {
$file = $_.fullname
echo $file
(get-content $file) | where {$_ -notmatch "^.*\#(end)?region.*$" } | out-file $file
}
Run this in your solution folder and support the movement against C# regions!
August 12, 2010 | 6 comments
- wea·sel·ly (adj.)
- Resembling or suggestive of a weasel.
Yesterday, Parcelforce called me at work to say they tried to deliver a package for me the day before, but couldn’t because I wasn’t around to sign for it.
I wasn’t expecting anything, but I like getting parcels, and thought maybe it was some long-forgotten internet purchase finally shipped. They wanted to arrange redelivery that afternoon, and asked for a couple of names of people who could sign for it just in case I was out (it was around 11am and I knew I would be stepping out briefly for lunch).
But twenty four hours later nothing has arrived. I think it was actually a recruitment agent, and the colleauges I gave as co-signatures will be getting some annoying calls soon :(
August 10, 2010 | 2 comments
Just spotted this in a project I’m working on:
public static string GetExceptionAsString(this Exception exception)
{
return string.Format("Exception message: {0}. " + Environment.NewLine +
"StackTrace: {1}. {2}", exception.Message, exception.StackTrace,
GetAnyInnerExceptionsAsString(exception));
}
Writing code like this should be a shooting offense.
But wait, there’s more! Check out its usage:
try
{
...
}
catch (Exception ex)
{
log.InfoFormat("Error occured:{0}.", ex.GetExceptionAsString());
}
Agh!
Code like this demonstrates a complete misunderstanding of CLR exception basics — inner exceptions and formatting — and also log4net. All that hand-rolled formatting could simply be replaced with:
- GetExceptionAsString() -> Exception.ToString()
- ILog.InfoFormat(format, args) -> ILog.Info(message, exception)
June 25, 2010 | 6 comments
Prism’s event aggregator is great for decoupling UI state changes when UI events occur, but sometimes you need to perform some larger, long-running task on a background thread — uploading a file, for example.
Here’s a quick example of an encapsulated event handler listening off the Prism event bus, and using Windsor’s IStartable facility to handle event subscription:
public class TradeCancelledEventHandler : ICompositePresentationEventHandler, IStartable
{
private readonly IEventAggregator eventAggregator;
protected TradeCancelledEventHandler(IEventAggregator eventAggregator)
{
if (eventAggregator == null)
throw new ArgumentNullException("eventAggregator");
this.eventAggregator = eventAggregator;
}
public void Start()
{
// Register to receive events on the background thread
eventAggregator
.GetEvent<TradeCancelledEvent>()
.Subscribe(Handle, ThreadOption.BackgroundThread);
}
public void Stop()
{
eventAggregator
.GetEvent<TradeCancelledEvent>()
.Unsubscribe(Handle);
}
void Handle(TradeCancelledEventArgs eventArgs)
{
// ... do stuff with the event
}
}
Each event handler is effectively a little service running in the container. Note ICompositePresentationEventHandler is a simple role interface that allows us to register them all at once in the IoC container:
public interface ICompositePresentationEventHandler {}
...
container.AddFacility<StartableFacility>();
// Register event handlers in container
container.Register(
AllTypes
.Of<ICompositePresentationEventHandler>()
.FromAssembly(Assembly.GetExecutingAssembly()));
June 24, 2010 | Leave your comment
In the first two posts I talked about commands and command handlers. Now we need to wire them up to invoke them from your service endpoint.
- Brownfield CQRS part 1 – Commands
- Brownfield CQRS part 2 – Command Handlers
- Brownfield CQRS part 3 – Queries, Parameters and Results
- Brownfield CQRS part 4 – Command Dispatcher
Command Dispatcher
When a command arrives, you simply look up the corresponding handler from your IoC container and invoke it. This responsibility is delegated to a command dispatcher object:
public interface ICommandDispatcher
{
void Dispatch<T>(T command) where T : ICommand;
}
public class CommandDispatcher : ICommandDispatcher
{
private readonly IWindsorContainer container;
public CommandDispatcher(IWindsorContainer container)
{
if (container == null) throw new ArgumentNullException("container");
this.container = container;
}
public void Dispatch<T>(T command) where T : ICommand
{
if (command == null) throw new ArgumentNullException("command");
var handler = container.Resolve<ICommandHandler<T>>();
ErrorIfNoHandlerForCommandFound(handler);
handler.Handle(command);
}
private static void ErrorIfNoHandlerForCommandFound<T>(
ICommandHandler<T> handler) where T : ICommand
{
if (handler == null)
throw new NoHandlerForCommandException(typeof(T));
}
}
Then we simply inject the command dispatcher into the WCF service and invoke it whenever a command is received:
[ServiceBehavior]
public class BookingService : IBookingService
{
private readonly ICommandDispatcher commands;
[OperationContract]
public void BookTable(BookTableCommand command)
{
if (command == null) throw new ArgumentNullException("command");
commands.Dispatch(command);
}
}
Many of you will note that this is very similar to Udi Dahan’s Domain Events aggregator — the only major difference is CQRS commands are only ever handled by one handler, where domain events are broadcast to anyone who’s listening.
Scaling out
Note this is a synchronous command dispatcher — commands are handled as soon as they arrive. An asynchronous/high-volume system may simply put them in a queue to be executed later by some other component.
Final thoughts
This really is a very introductory series to refactoring an existing application to move towards CQRS. We haven’t even touched on the main goal of CQRS yet — all we’ve done is put clear command/query contracts between our client and server.
It may not sound like much, but doing so allows us to mask non-CQRS components in our system — an anti-corruption layer of sorts — and allows us to proceed refactoring them internally to use different models and storage for commands and queries.
June 17, 2010 | 10 comments


