Saturday, November 29, 2008

Ninject MessageBroker Update

It has been a long time (10 months) since I worked with the Ninject MessageBroker and a couple things have changed since my last post. In the old version you had to connect the MessageBroker as a kernel component by hand. Since then the extension environment has been flushed out a lot more. Now you can register the MessageBrokerModule when constructing your kernel object.



using System;
using System.Diagnostics;
using System.Net;
using System.Text.RegularExpressions;
using Ninject.Core;
using Ninject.Extensions.MessageBroker;

namespace NinjectMessageBroker
{
internal class Program
{
private static void Main()
{
// Intialize our injection kernel adding message broker functionality.
using (var kernel = new StandardKernel(new[] { new MessageBrokerModule() }))
{
// Get the event publisher. It reads the current time and fires an event
var pub = kernel.Get<TimeReader>();
Debug.Assert(pub != null);

// Get the subscriber, it waits to get the current time and writes it to stdout
var sub = kernel.Get<TimeWriter>();
Debug.Assert(sub != null);

// Verify that they were wired together
Debug.Assert(pub.HasListeners);
Debug.Assert(sub.LastMessage == null);

// Get the current time. It should automatically let the TimeWriter know
// without either of them ever knowing of one another.
pub.GetCurrentTime();

// Wait to exit.
Console.ReadLine();
}
}
}

internal class TimeWriter
{
public string LastMessage { get; set; }

[
Subscribe("message://Time/MessageReceived")]
public void OnMessageReceived(object sender, EventArgs<string> args)
{
LastMessage = args.EventData;
Console.WriteLine(LastMessage);
}
}

internal class TimeReader
{
public bool HasListeners
{
get { return (MessageReceived != null); }
}

[
Publish("message://Time/MessageReceived")]
public event EventHandler<EventArgs<string>> MessageReceived;

/// <summary>
///
Gets the current time and updates all subscribers.
/// </summary>
public virtual void GetCurrentTime()
{
string text = GetWebPage();
var regex = new Regex(@"\d\d:\d\d:\d\d");
MatchCollection matches = regex.Matches(text);
string time = ((matches.Count == 2) ? matches[1] : matches[0]).Value;
SendMessage(time);
}

/// <summary>
///
Gets the contents of a web page as a string.
/// </summary>
/// <returns></returns>
private static string GetWebPage()
{
const string url = "http://www.time.gov/timezone.cgi?Eastern/d/-5";
var webClient = new WebClient();
return webClient.DownloadString(url);
}

/// <summary>
///
Sends the message to all subscribers in a threadsafe manner.
/// </summary>
/// <param name=
"message">The message.</param>
public void SendMessage(string message)
{
EventHandler<EventArgs<string>> messageReceived = MessageReceived;

if (messageReceived != null)
{
messageReceived(this, new EventArgs<string>(message));
}
}
}

public class EventArgs<TData> : EventArgs
{
public new static readonly EventArgs<TData> Empty;

static EventArgs()
{
Empty = new EventArgs<TData>();
}

private EventArgs()
{
}

public EventArgs(TData eventData)
{
EventData = eventData;
}

public TData EventData { get; private set; }
}
}

Friday, November 28, 2008

C++ if statement oddity

I found that you can do work such as assigning a variable and executing a method outside of the main expression of an if statement. For example:



    if(hRes = GetApplicationState(), NT_SUCCESS(hRes))
{
// Do something
}



Yes, that is a comma inside of the if statement. To the left of the comma is executed first and then the if statement uses the right side as its evaluation expression.

Open Source Projects

I had two open source projects: Ensurance, and IMAPI.Net.

  • Ensurance did not really fit into any particular group. It was a tool for me while Spec# was still a research project at MS. I wanted to be able to use pre/post conditions, parameter constraints, and tie them into logging and debugging. I don’t think that Spec# will do the last bit, but I am really looking forward to its release.
  • IMAPI.Net is a C# cd authoring library that wraps the IMAPI system in windows to allow programmers of any application to write to CD. It supports data and audio discs. It was expensive to test the library and the COM issues were a huge problem for a while.
    • PInvoke.net was a good help for the most part, but the marshalling took a long time to get right. I started the project back in .net 1.1 while working on my BS - and it worked. With each .NET release the project would have been easier to write with the COM interop support increasing. I used to be the lead of the XPBurn component project on GotDotNet before it shut down; in truth though, I had stopped supporting it a couple months before that. No one would read directions, read the forum, follow any kind of guidelines and would essentially expect me to figure out why they are using the code wrong. It became too much hassle in the end for what I got out of the project. It was a great learning experience though.

Both projects are essentially dead and I will be closing down the Ensurance  project on CodePlex. I will leave IMAPI.Net up on google code in case anyone ever finds use for the code. If I get the time I will try to add my PInvoke code to the wiki so others don’t have to work as hard as I did.