Improved annoyatron

I think that it's good to keep your hand in with some plain old C programming once in a while.  So I ocasionally mess around with microprocessors. I've been working on an improved annoyatron, with my version it will pretend to be a mobile phone - by playing a simple ringtone. This is what it currently looks like:

annoyatron 2.0

 I've used an AVR ATmega168 microprocessor, which is over spec, but I had a couple of them lying around.  In fact all of the other components except for the button cell battery and holder were things that I had sitting around.  What tends to happen is that before I throw anything away, I take it to bits to see if I can remove anything.  Even a salvaged switch can be useful one day.  And it's fun to take stuff apart :-)

So ... what I'll try to do is post more about this - what development tools I've used and what I have discovered along the way.  I'll be sure to refer back to it if nobody else does.

Tron Legacy

My wife told me that they were making a new Tron movie (the original came out in 1982) but even better than that, Daft Punk are doing the soundtrack. Sounds good, I really hope they don't mess this film up. So of course, I had to try and find a trailer, which I found here:
http://www.youtube.com/watch?v=a1IpPpB3iWI

Looks good so far. But then I also went and found this: http://www.youtube.com/watch?v=TbBH3bNyge4 it's rework but still cool, Daft Punk are probably still fiddling with it anyway.  But I can't wait to hear the other stuff that they come up with, I think I'm gonna like it...

Custom wsdl from WCF

I wanted my WCF service to export specific metadata.  Essentially I am building it contract-first and I only want the users to see the hand-crafted wsdl and xsd files that have been created.  If the web service was running in IIS that would be easy, I'd simply set the location of the metadata explicitlly in the web.config file, like this:

 

<serviceBehaviors>

  <behavior name="MyBehavior">

    <serviceMetadata httpGetEnabled="true"

    externalMetadataLocation="MyCustomWsdl.wsdl" />

    <serviceDebug includeExceptionDetailInFaults="false" />

  </behavior>

</serviceBehaviors>

 

But this time my WCF service is running inside a Windows Service, so I can't just let IIS serve the wsdl as a page, unless I install the wsdl file on some other web server, which makes for a deployment nightmare.  So I set about finding out how to override the mechanism that WCF uses for sending the auto-generated wsdl.  I was thinking about overriding that.  I found that I could easily add a class that implements the IWsdlExportExtension and IEndpointBehavior interfaces, and it did allow me to do some fiddling with the generated wsdl, but not at the level I wanted.  I wanted total control, essentially streaming the files that had been hand crafted so carefully.  For a minute, I even considered implementing an HttpListener to send out the files :-0

 

The solution that I have settled on is to add another WCF service to my Windows Service.  This is a simple WCF service that responds to http GET commands, the interface looks like this:

 

[ServiceContract]

public interface ICustomWsdl

{

   [OperationContract]

   [WebGet()]

   Stream MetaData(string name, string extension);

}

 

By returning a Stream, we are able to avoid sending the xml decoration around the response, which would happen if we returned a string, for example.  The basic implementation of this service looks like this:

 

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]

public class CustomWsdlService : ICustomWsdl

{

   private string renameXsd(string src)

   {

      XmlDocument xdoc = new XmlDocument();

      xdoc.LoadXml(src);

      XmlNodeList xmlnodes = xdoc.GetElementsByTagName("xsd:include");

      updateNodes(xmlnodes);

      xmlnodes = xdoc.GetElementsByTagName("xsd:import");

      updateNodes(xmlnodes);

      return xdoc.InnerXml;

   }

 

   private void updateNodes(XmlNodeList xmlnodes)

   {

      for (int i = 0; i < xmlnodes.Count; i++)

      {

         string xsdName = xmlnodes[i].Attributes["schemaLocation"].Value as string;

         if (!string.IsNullOrEmpty(xsdName))

         {

            string newName = "MetaData?name="

              + Path.GetFileNameWithoutExtension(xsdName) + "&extension=xsd";

            xmlnodes[i].Attributes["schemaLocation"].Value = newName;

         }

      }

   }

 

   public Stream MetaData(string name, string extension)

   {

      string path =

         Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

      string src =

         renameXsd(File.ReadAllText(path + "\\" + name + "." + extension));

      return new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(src));

   }

}

 

To make it work we need to add these settings in the config file:

 

<system.serviceModel>

  <behaviors>

    <endpointBehaviors>

      <behavior name="WebEndpointBehavior">

        <webHttp/>

      </behavior>

    </endpointBehaviors>

  </behaviors>

 

  <bindings>

    <webHttpBinding>

      <binding name="HttpBindingConfig"/>

    </webHttpBinding>

  </bindings>

 

  <services

    <service name="CustomWsdlService">

      <endpoint address="wsdl"

      behaviorConfiguration="WebEndpointBehavior" binding="webHttpBinding"

      contract="Aggregation.Broker.Core.ICustomWsdl"

      bindingConfiguration="HttpBindingConfig">

        <identity>

          <dns value="localhost" />

        </identity>

      </endpoint>

      <host>

        <baseAddresses>

           <add baseAddress="http://localhost:8731/Test/" />

        </baseAddresses>

      </host>

    </service>

  </services>

</system.serviceModel>

 

It will serve up xsd and wsdl files as long as they are in the same folder as the running assembly.  Since it can be called via http GET, you can test it in a browser, like this:

 

http://localhost:8731/Test/wsdl/MetaData?name=MyWsdlFileName&extension=Wsdl

 

...which would serve up a wsdl file named MyWsdlFileName.wsdl as long as it was in the same folder as the running binaries.  Any import or include statements in the metadata will be automatically remapped to the same serving method, so the wsdl can reference seperate xsd files (indeed, xsd files can also reference other xsd files).  All this means that another WCF service can use this in the config:

 

<serviceMetadata httpGetEnabled="true" externalMetadataLocation="URL_AS_ABOVE" />

 

Job done, I now have total control of my metadata, I just place the wsdl and xsd files in with the binaries of my Windows Service.  Finally, I just need to host this new WCF service in the existing Windows Service, which is easy.  Hopefully, that is not a bad solution.  I've tested it by pointing SoapUI at some metadata presented this way, and it seems fine, happy days.

A new lock statement for C#

I'm working on a lot of multithreaded code at the moment.  In the past I have made use of the lock keyword in C#, but I'm not doing that anymore because it is much better to have a timeout.  However, I don't like having lots of sections like this in my code:

 

if (System.Threading.Monitor.TryEnter(objLock, TIMEOUT))

{

    try

    {

        // do stuff here...

    }

    finally

    {

        System.Threading.Monitor.Exit(objLock);

    }

}

 

...which is the equivalent of using the lock statement, but with a timeout specified.  Still, what I'd like to see in my code is something like this:

 

lock (objLock,TIMEOUT)

{

    // do stuff here...

}

 

Which would be more pretty.  And since I like pretty code, I decided to see how close I could get to that.  This is my current solution:

 

public static class Lock

{

    public static T Try<T>(object objLock, int timeout, Func<T> f)

    {

        if (System.Threading.Monitor.TryEnter(objLock, timeout))

        {

            try

            {

                return f.Invoke();

            }

            finally

            {

                System.Threading.Monitor.Exit(objLock);

            }

        }

        return default(T);

    }

 

    public static void Try(object objLock, int timeout, Action f)

    {

        if (System.Threading.Monitor.TryEnter(objLock, timeout))

        {

            try

            {

                f.Invoke();

            }

            finally

            {

                System.Threading.Monitor.Exit(objLock);

            }

        }

    }

}

 

So far, that is as close as I can get, it means that I can do two things:

 

Lock.Try(objLock, TIMEOUT, delegate

{

    // stuff here...

});

 

or, if I need to return a value, then this:

 

return Lock.Try<int>(objLock,TIMEOUT,delegate

{

    // stuff here...

    return 0;

});

 

Because the second example uses generics, then I can return anything I like by specifying the type inside the angled brackets.  Now I feel that my code is a lot more prettier which is a nice way to finish off on a Friday.