27 April 2010

A very basic MEF sample using ImportMany

If you have been programming since the mid-80’s and have been a IT professional for over 17 years it does not happen often anymore that you get mesmerized by a beautiful piece of architecture, but recently it happened twice to me in a very short time, and one of the causes was the Managed Extensibility Framework or MEF. Almost everyone has built some or other extensible architecture at one point but never before I have seen something as simple, elegant and universally applicable as this.

This article describes the setup of a very basic MEF driven application, using VS2010 Pro and .NET 4. It’s kind of abstract: a hosting component that accepts two strings, and calls one or more MEF components to actually do the manipulation. Every component has its own library, which may seem a bit overkill, but I wanted to check out the extensibility to the max. So I started out with an empty solution and then used the following track

1. Create a class library "Contracts"
This will contain the interface IMyComponent by which the components communicate:
namespace Contracts
{
  public interface IMyComponent
  {
    string Description { get; }
    string ManipulateString(string a, string b);
  }
}

as you can see, one hell of a complex component we are making here ;-)

2. Create a class library "ImportingLib"
This will contain the host, i.e. the class that actually hosts and calls the components. Add a reference to the "Contracts" projects as well as to "System.ComponentModel.Composition". Then Add a class "Importer", with the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using Contracts;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using System.IO;

namespace ImportingLib
{
  public class Importer
  {
    [ImportMany(typeof(IMyComponent))]
    private IEnumerable<IMyComponent> operations;

    public void DoImport()
    {
      //An aggregate catalog that combines multiple catalogs
      var catalog = new AggregateCatalog();
      //Adds all the parts found in all assemblies in 
      //the same directory as the executing program
      catalog.Catalogs.Add(
       new DirectoryCatalog(
        Path.GetDirectoryName(
         Assembly.GetExecutingAssembly().Location)));

      //Create the CompositionContainer with the parts in the catalog
      CompositionContainer container = new CompositionContainer(catalog);

      //Fill the imports of this object
      container.ComposeParts(this);
    }

    public int AvailableNumberOfOperations
    {
      get
      {
        return (operations != null ? operations.Count() : 0);
      }
    }

    public List<string> CallAllComponents( string a, string b)
    {
      var result = new List<string>();
      foreach( var op in operations )
      {
        Console.WriteLine(op.Description);
        result.Add( op.ManipulateString(a,b ));
      }
      return result;
    }
  }
}

This deserves some explanation. This host imports 0 or more (ImportMany) components implementing IMyCompoment - and wants them delivered into the private property operations, thank you. The method "DoImport" can be called to initialize this object - Path.GetDirectoryName( Assembly.GetExecutingAssembly().Location) gives the directory in which the executing assembly (i.e. the program or the test) project resides, and by creating a DirectoryCatalog on that directory and then adding that to the main AggregateCatalog you make MEF automatically start searching all the assemblies in the directory where the calling program resides. Property AvailableNumberOfOperations of the Importer returns the number of found operations, and CallAllComponents calls all the IMyComponent exporting components and returns the result in one go.

To prove this actually works, we continue:

3. Create a class library "ExportingLib1"
Add a reference to "Contracts" and "System.ComponentModel.Composition", then add a class "TestComponent1" with the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Contracts;
using System.ComponentModel.Composition;

namespace ExportingLib1
{
  [Export(typeof(IMyComponent))]
  public class TestComponent1 : IMyComponent
  {
    #region IMyComponent Members
    public string Description
    {
      get { return "Concatenates a and b"; }
    }

    public string ManipulateString(string a, string b)
    {
      return string.Concat(a, b);
    }
    #endregion
  }
}

as you can see, this utterly exiting class exports IMyComponent, delivers a description of itself and concatenates the two strings to 1

4. Create a class library "ExportingLib2"
Add a reference to "Contracts" and "System.ComponentModel.Composition", then add a class "TestComponent2" with the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Contracts;
using System.ComponentModel.Composition;

namespace ExportingLib2
{
  [Export(typeof(IMyComponent))]
  public class TestComponent2 : IMyComponent
  {
    #region IMyComponent Members
    public string Description
    {
      get { return "Removes b from a"; }
    }

    public string ManipulateString(string a, string b)
    {      
      return a.Replace(b, string.Empty);
    }
    #endregion
  }
}
Again, a very complex class ;-), this time it removes all occurrences from b in a.

5. Create a test project "ImportingLib.Test"

Add references to ImportingLib, ExportingLib1 and ImportingLib2 and add the following test methods:

[Test]
public void TestCountComponents()
{
  var t = new Importer();
  t.DoImport();
  Assert.AreEqual(2, t.AvailableNumberOfOperations);
}

[Test]
public void TestOperations()
{
  var t = new Importer();
  t.DoImport();
  var result = t.CallAllComponents("all are equal ", "all");
  Assert.IsTrue( result.Contains( "all are equal all"));
  Assert.IsTrue( result.Contains( " are equal "));
}
If you followed my ‘recipe’ correctly, both tests will succeed. In addition, since you have added a Console.WriteLine in the CallAllComponents method, on the standard console output you will see "Concatenates a and b" and "Removes b from a", indicating the components that have been called. As you see, nowhere in code the components are actually instantiated - this is all done by MEF. The fun thing is, just by removing the reference to either ExportingLib1 or ExportingLib2 you can make the test fail. Nowhere are any explicit links between host and components but in the actual calling program itself, and those links are only made by the very presence of an assembly in the directory of the current executing program, or in this case, the test project.

So, you can dump more assemblies exporting IMyComponent - and the host will automatically pick them up. #Thatwaseasy

Parts of this sample are based on this description

Update 06-07-2012: I've added a full demo solution to this post to show how things are put together

01 April 2010

Caveats when migrating existing CLSA.NET objects to Silverlight

So you have been working for a while with CSLA .NET by Rockford Lhotka and now you want – like me – jump on the Silverlight bandwagon. So you want to reuse the business objects in Silverlight. There are some nice samples in the cslalight samples but when I started to try to use my own business objects, things did not run so smoothly as the samples suggest.

The samples by Rockford show the general outline:

  • You make a second assembly into which you add the exisiting business class source files as a link
  • You start adding specific Silverlight functionality surrounded by
    #if SILVERLIGHT (…) #endif preprocessor directives
  • You make sure that the server stuff like data access is not active in the Silverlight configuration (#if !SILVERLIGHT)
  • You add a Silverlight-specific factory method to load an object, that looks a bit like this:
public static void Get(int id, 
  EventHandler<DataPortalResult<MyBusinessClass>> callback)
{
  var dp = new DataPortal<MyBusinessClass>( );
  dp.FetchCompleted += callback;
  dp.BeginFetch( new IdCriteria(id) );
}

If you try to call this from your Silverlight client the result is - unless you are very lucky - most likely that the sky starts caving in. Turns out there are a few 'hidden requirements' –or at least some less apparent ones. Maybe there are more, but this was what I found so far:

  • Both the Silverlight and the full framework assemblies must have the same name, so even if your projects are called MyLib.Server and MyLib.Client, the resulting dll’s must have the same name, for example MyLib.dll.
  • If your full framework assembly is signed, your Silverlight assembly should be signed as well. They then also must have the same version number – all the way to the build number. This is important – and it took me the most time before the penny dropped.
  • All the Silverlight classes must have public constructors. So you add
#if! SILVERLIGHT   
  private MyBusinessClass()
  {
  }
#else
  public MyBusinessClass()
  {
  }
#endif
  • Properties should be defined in the ‘modern’ format. You have still properties in this format?
private string _oldProp = string.Empty;

public string OldProp
{
  get
  {
    return _oldProp;
  }	 
  set
  {
    if (value == null) value = string.Empty;
    if (!_oldProp.Equals(value))
    {
      _oldProp = value;
      PropertyHasChanged("OldProp");
    }
  }
}
Tough luck. Change that into the 'new' form, e.g.
private static PropertyInfo NewPropProperty = 
  RegisterProperty(c => c.NewProp);
public string NewProp
{
	get { return GetProperty(NewPropProperty); }
	set { SetProperty(NewPropProperty, value); }
}
  • Criteria objects should have public constructors as well, and should be public classes – that is, if you have defined them as private classes inside your business object, you should make them public
  • Your Criteria should implement IMobileObject. The easiest way is to let your class descend from CriteriaBase, but then you will find out that although the class is serialized to the server, the properties are not. Turns out that for Criteria objects the property format has changed too. In the past you could just make a simple class with a few getters and setters, now you have to make something along this line:
[Serializable]
public class IdCriteria : CriteriaBase
{
  public static PropertyInfo<int> IdProperty = 
    RegisterProperty(typeof(IdCriteria), new PropertyInfo<int>("Id"));
  public int Id
  {
    get { return ReadProperty(IdProperty); }
    set { LoadProperty(IdProperty, value); }
  }
  public IdCriteria() { }

  public IdCriteria(int id)
  {
    Id = id;
  }
}

So, although CLSA ‘light’ promises a lot of reuse (which is true of course, in the case of business and validation rules) you need a lot of extra plumbing to get going. And mind you, this is a simple single object that I only read – I haven’t covered lists yet, nor updates and deletes. The power of CSLA can come to Silverlight – but certainly for existing libraries it is not quite a free ride. But then again - this is Silverlight, so it should run on Windows Phone 7 series as wel... which will be my next experiment. I will keep you posted!

01 March 2010

Running CSLALight 3.8.2 under .NET 4 and Silverlight 4

Update December 23, 2013: this is article is pretty much outdated. Currently it gets a lot of traffic. I hope some people reading it would like to leave a comment and tell me WHY the are reading it

CSLA .NET by Rockford Lhotka is a business layer framework, but it does not run under .NET4 and Silverlight 4 yet. Fortunately this framework comes with sources, and I set out to get a simple sample application to run under Silverlight 4. As always, it is a lot more work to find out what to do than to actually do it, but eventually I was successful. To make life for those who want to follow me a little harder: I am using Visual Studio 2010RC and the Silverlight 4 tools beta. I know those are not supposed to work together, but if you follow this procedure you actually can run Silverlight 4 tools inside the RC. This procedure, however, included hacking an installer and then editing some registry keys. Follow this procedure at your own risk. It worked for me, but maybe the procedure for getting CSLA to run under .NET 4 and Silverlight 4 may work under VS2010 B2 as well.

1. Download these files
  • cslalightcs-3.8.2-100201.zip
  • lightsamples-3.8.2-100201.zip

Which can all be found on the CSLA.NET site.

2. Unzip the files in working directories

The net result should be something like this
CSLA
  - clsacs
  - clsalightcs
  - Dependencies
  - README.txt
LightSamples
  - cslalight
  - readme.txt

3. Compile clsacs.sln for .NET 4.0
  • Start Visual Studio 2010, and open the solution clsacs.sln in CSLA\cslacs.
  • Let Visual Studio 2010 convert the project
  • right-click the csla project, select properties and change the target framework to .NET 4.0
  • Change the active solution configuration to “Release”
  • Rebuild the solution. This will give some errors. If you check the clsa project’s references, you will see warning signs indicating missing assemblies, which are:
    • PresentationCore
    • PresentationFramework
    • System.Printing
    • System.Runtime.Serialization
    • System.ServiceModel
    • System.Workflow.Runtime
    • WindowsBase
  • Remove these references and replace them by their .NET 4.0 brethren.
  • Add a reference to System.Xaml
  • Rebuild the solution. You will get a whole lot of warnings but CSLA will compile.
4. Compile cslalightcs.sln for Silverlight 4
  • Start Visual Studio 2010, and open the solution clsalightcs.sln in CSLA\cslalightcs.
  • Let VS2010 convert the project
  • right-click the Cslalight project, select properties and change the Target Silverlight Version to 4.0
  • Add a reference to System.Net
  • Change the active solution configuration to “Release”
  • Rebuild the solution. Once again, a whole lot of warnings but CSLAlight will compile

5. Convert and compile the SimpleApp sample

If you browse into LightSamples\cslalight\cs\SimpleApp with the Windows Explorer you will find a simple CSLA/CSLA light solution that demonstrates the basic setup of the CSLA data portal for Silverlight. We will convert this application to work under our freshly created CSLA and CSLALight libraries.

  • Open the SampleApp.sln solution with Visual Studio 2010
  • Let Visual Studio 2010 convert the solution
  • Click “Yes” to upgrade to .NET 4.0 and ignore further errors
  • The solution contains 4 projects.
    • Set the Target Silverlight Version of Library.Client and SimpleApp to Silverlight 4
    • Set the target framework for Library.Server to .NET 4.0. No need to change SimpleApp.Web, Visual Studio has already done that
  • In project Library.Client:
    • Check the references. You will find “Csla” missing.
    • Remove the reference
    • Click Add Reference/Browse
    • Browse to CSLA\cslalightcs\Csla\ClientBin.
    • Add References to Csla.dll and System.Windows.Interactivity.dll
  • Repeat the procedure for SimpleApp
  • In project Library.Server:
    • Check the references. You will find “Csla” missing.
    • Remove the reference
    • Click Add Reference/Browse
    • Browse to CSLA\cslacs\Csla\bin\Release
    • Add a Reference to Csla.dll
  • Repeat the procedure for SimpleApp.Web.

6. Change the ServiceReferences.ClientConfig

This actually took me the longest, because I did not understand the problem. If you run the application (right click SimpleApp.Web/SimpleAppTestPage.aspx and click “View in Browser”), enter some values “for “Name” and “City” and hit “Save” you get an error indicating that there is no endpoint for contract “WcfPortal.IWcfPortal”.

Apparently something has changed in how Service Contracts are referenced in Silverlight 4. The solution turns out to be this:

  • open the ServiceReferences.ClientConfig file in the SimpleApp project
  • Locate the text contract="Csla.WcfPortal.IWcfPortal" 
  • Remove the “Csla.” prefix, including the dot, so that only contract="WcfPortal.IWcfPortal" remains
  • Run SimpleApp.Web/SimpleAppTestPage.aspx again

Hit some values for “Name” and “City” again, hit “Save” and the text “Inserted Client” appears. You can set some breakpoints to see CSLA actually goes back to the server for that. And, of course, you can right-click on the Silverlight application, click “Silverlight” on the ‘context menu’ and see that actually runs under Silverlight 4

This of course guarantees by no means that all the features of Csla will work under Silverlight 4 but at least we can go forward playing around in this new environment.

28 February 2010

Injecting logic in the middle of an algorithm using “Func<T>” function parameters

Sometimes you run into a situation in which you have a very similar complex pieces of logic, that only differ somewhere deep inside. This happens especially when you are dealing with legacy code that requires all kinds of weird initializers. Consider the following example, which is similar to something I ran into deep down in a CSLA library:

private void DataPortal_Fetch(string a, string b, string c)
{
  var helper = new LoaderHelper();
  helper.Init();
  LegacyObjectCollection result = 
OldStaticHelper.GetByThreeStrings( a, b, c); IsReadOnly = false; result.ForEach(p => Add(SomeNewObject.Get(p, helper))); RaiseListChangedEvents = false; IsReadOnly = true; } private void DataPortal_Fetch(string a, int n) { var helper = new LoaderHelper(); helper.Init(); LegacyObjectCollection result = OldStaticHelper.GetByOtherKeys( a, n); IsReadOnly = false; result.ForEach(p => Add(SomeNewObject.Get(p, helper))); RaiseListChangedEvents = false; IsReadOnly = true; }

The idea clearly was to call some legacy code and transform this into a list of “SomeNewObject”. But the annoying thing about the legacy code was that all kinds of helpers needed to be initialized before OldStaticHelper could be called. And then the logic of transforming the data had been duplicated as well. There are a number of ways to refactor this, but because I was fooling around with functional programming concepts at the time, I tried the following, which almost worked:

private void DataPortal_Fetch(string a, string b, string c)
{
  FetchData(OldStaticHelper.GetByThreeStrings( a, b, c)); 
}

private void DataPortal_Fetch(string a, int n)
{
  FetchData(OldStaticHelper.GetByOtherKeys( a, n));
}

private void FetchData(Func<LegacyObjectCollection> loaderMethod)
{
  var helper = new LoaderHelper();
  helper.Init();
  LegacyObjectCollection result = loaderMethod();
  IsReadOnly = false;
  result.ForEach(p => Add(SomeNewObject.Get(p, helper)));
  RaiseListChangedEvents = false;
  IsReadOnly = true;
}

Although this compiled an ran, it did not work as expected. Upon calling “FetchData” the OldStaticHelper.GetBy… method was instantly executed, in stead of of when “result = loaderMethod()” was called. And I just stated that it would not work unless the “helper” code was initialized. Thus, I needed to use delegates:

private void DataPortal_Fetch(string a, string b, string c)
{
  FetchData(() => OldStaticHelper.GetByThreeStrings( a, b, c)); 
}

private void DataPortal_Fetch(string a, int n)
{
  FetchData(() => OldStaticHelper.GetByOtherKeys( a, n));
}
Or, for those not familiar with the lambda syntax:
private void DataPortal_Fetch(string a, string b, string c)
{
  FetchData(delegate { return OldStaticHelper.GetByThreeStrings( a, b, c)}); 
}

private void DataPortal_Fetch(string a, int n)
{
  FetchData(delegate { return OldStaticHelper.GetByOtherKeys( a, n)});
}
Using this technique you can 'inject' a piece of logic into a larger algorithm, eliminating the need to duplicate code or making all kinds of in-between data sets

25 January 2010

A generic convertor for IEnumerable<T>

Apart from ForEach<T>, as I described in my previous post, I noticed the absence of ConvertAll<T> on everything but List<T> as well. Pretty annoying when I wanted to convert a list of business objects of So I extended my static class GenericUtilities with another extension methdo

using System;
using System.Collections.Generic;

namespace LocalJoost.Utilities
{
  public static class GenericExtensions
  {
    // previous code for ForEach omitted.

    public static IEnumerable<TC> ConvertAll<T, TC>(
      this IEnumerable<T> inputList, 
      Converter<T, TC> convert)
    {
        foreach( var t in inputList )
        {
            yield return convert(t);
        }
  }
}
This permitted me to do something like this:
return ListRubriek.Get()
  .ConvertAll(p => new CascadingDropDownNameValue(
        p.Omschrijving, p.Id.ToString()))
  .ToArray();
to easily convert a list of CSLA business objects into a list that could be used in an ASP.NET Ajax Cascading dropdown. Nothing special for the veteran functional programmer I guess but still, useful.

This is actually the 2nd version - thanks to Jarno Peschier for some constructive criticism

19 January 2010

One ForEach to rule them all

I ran into this when I was investigating functional programming in C#. That’s been around for a while, but apart from using it for traversing or modifying collections or lists, I never actually created something that was making use of a function parameter.

Anyway, one of my most used constructs is the ForEach<T> method of List<T>. I always thought it to be quite annoying that it is only available for List<T>. Not for IList<T>, ICollection<T>, or whatever. Using my trademark solution pattern – the extension method ;-)
I tried the following:

using System;
using System.Collections.Generic;

namespace LocalJoost.Utilities
{
  public static class GenericExtensions
  {
    public static void ForEach<T>(this IEnumerable<T> t, Action<T> action)
    {
      foreach (var item in t)
      {
        action(item);
      }
    }
  }
}

And that turned out to be all. IList<T>, ICollection<T>, everything that implements IEnumerable<T> – now sports a ForEach method. It even works for arrays, so if you have something like this

string[] arr = {"Hello", "World", "how", "about", "this"};
arr.ForEach(Console.WriteLine);
It nicely prints out

Hello
World
how
about
this

I guess it's a start. Maybe it is of some use to someone, as I plod on ;-)

18 November 2009

A light-weight .NET framework for publishing Layar layers using WCF and Unity (C#)

Thus speaks Wikipedia:

Augmented reality (AR) is a term for a live direct or indirect view of a physical real-world environment whose elements are merged with (or augmented by) virtual computer-generated imagery - creating a mixed reality.

Amen. Fact is that AR is currently as hot a nuclear reactor core making its way to China, and that everyone and his aunt are scrambling to get a piece of the action. So why not me ;-)

On November 9th this year, my colleague Jeroen Prins, who did some prototyping with Layar, pushed a HTC Hero in my hands with the words “see if you can do something nice with it”. So in a few evenings I created a little framework for making Layar layers in an easier and consistent way. It is based upon some of Jeroen’s prototype, but since he insisted on not having credits for this I won’t give him any ;-). The framework uses the Enterprise Library, most notably Unity, and I assume you are familiar with it.

Since WCF can be bent in almost every direction as far as generating content is concerned, I decided to use it for my solution. I started, as you always start, with the data contract. The object model is pretty simple: a Layer object has Point-Of-Interest (Poi) objects, a Poi has Action objects. If you study the Layar GetPointsOfInterest page for a few minutes you will see the implementation is WCF 101. Maybe 102 ;-). Contrary to my habits, I forego on the comments – those are all on the GetPointsOfInterest page. First, the Action object:

using System.Runtime.Serialization;

namespace LocalJoost.Layar
{
  [DataContract(Name = "Action")]
  public class Action
  {
    [DataMember(Name = "uri")]
    public string Uri { get; set; }

    [DataMember(Name = "label")]
    public string Label { get; set; }
  }
}

The member name is “Uri” (following the .NET coding guidelines) but with adding “Name=uri” in the DataMember attribute I tell WCF to serialize the member as “uri”, without the capital “U”, thus following exactly the Layer API description. This is standard WCF stuff. Then, the Poi class:

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace LocalJoost.Layar
{
  [DataContract (Name="POI")]
  public class Poi
  {
    public Poi()
    {
      Actions = new List();
    }
    [DataMember(Name = "actions")]
    public List Actions { get; set; }

    [DataMember(Name = "attribution")]
    public String Attribution { get; set; }

    [DataMember(Name = "distance")]
    public double Distance { get; set; }

    [DataMember(Name = "id")]
    public string Id { get; set; }

    [DataMember(Name = "imageURL")]
    public string ImageUrl { get; set; }

    [DataMember(Name = "lat")]
    public int Latitude { get; set; }

    [DataMember(Name = "lon")]
    public int Longitude { get; set; }

    [DataMember(Name = "line2")]
    public string Line2 { get; set; }

    [DataMember(Name = "line3")]
    public string Line3 { get; set; }

    [DataMember(Name = "line4")]
    public string Line4 { get; set; }

    [DataMember(Name = "title")]
    public string Title { get; set; }

    [DataMember(Name = "type")]
    public int Type { get; set; }
  }
}

and finally, the Layer object itself:

using System.Collections.Generic;
using System.Runtime.Serialization;

namespace LocalJoost.Layar
{
  [DataContract]
  public class Layer
  {
    public Layer()
    {
      Hotspots = new List();
    }

    [DataMember(Name = "nextPageKey")]
    public string NextPageKey { get; set; }

    [DataMember(Name = "morePages")]
    public bool MorePages { get; set; }

    [DataMember(Name = "hotspots")]
    public List Hotspots { get; set; }

    [DataMember(Name = "layer")]
    public string LayerName { get; set; }

    [DataMember(Name = "errorCode")]
    public int ErrorCode { get; set; }

    [DataMember(Name = "errorString")]
    public string ErrorString { get; set; }
  }
}

I move on to the whopping complex service contract:

using System.ServiceModel;
using System.ServiceModel.Web;

namespace LocalJoost.Layar
{
  [ServiceContract(Namespace = "www.yournamespacehere.nl/layar")]
  public interface ILayarService
  {
    [OperationContract]
    [WebGet(UriTemplate = "Layar/{layerName}/*", 
      ResponseFormat=WebMessageFormat.Json)]
    Layer GetLayerData(string layerName);
  }
}

which defines the output for this as being JSON, and a custom URI matching pattern which allows us to put the actual layer name in the URL. The * at the end means "and the rest is also accepted". Now the title of this posting says I was doing something with Unity, and here it comes: I define an equally complex interface for a Layar "provider" which will be used by the service implementation:

using System.Collections.Generic;

namespace LocalJoost.Layar
{
  public interface ILayarProvider
  {
    Layer Get(double? lat, double? lon, 
      int? radius, int? accuracy, 
      IDictionary requestParameters);
  }
}

The final piece of real code is the implementation of the ILayarService service contract, with apologies for the crappy layout, but some WCF class names are a wee bit long:

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.ServiceModel.Web;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using LocalJoost.Utilities.Unity;

namespace LocalJoost.Layar
{
  /// <summary>
  /// Layar service implementation
  /// </summary>
  public class LayarService : ILayarService
  {
    /// <summary>
    /// Request parameters
    /// </summary>
    private static NameValueCollection RequestParams
    {
      get
      {
        return WebOperationContext.Current != null ?          WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters
: null;
      }
    }

    private static readonly List<string> KeyWordsProcessed = 
      new List<string> { "lat", "lon", "radius", "accuracy" };

    /// <summary>
    /// Gets the layer data.
    /// </summary>
    /// <param name="layerName">Name of the layer.</param>
    /// <returns></returns>
    public Layer GetLayerData(string layerName)
    {
      try
      {
        if (WebOperationContext.Current != null )
        {
          Logger.Write("Layar call: " +             WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri);
        }
        // Note: layername is lowercase
        var provider =
          new UnityResolver(
             layerName.ToLowerInvariant()).Resolve<ILayarProvider>();

        // Collect the other parameters
        var reqParms = new Dictionary<string, string>();
        foreach( var key in RequestParams.Keys)
        {
          var keyS = key.ToString();
          if (!KeyWordsProcessed.Contains(keyS))
            reqParms.Add(keyS, RequestParams[keyS]);
        };
        
        return provider.Get(
          GetRequestDouble("lat"), GetRequestDouble("lon"),
          GetRequestInt("radius"), GetRequestInt("accuracy"),
          reqParms);
      }
      catch( Exception ex)
      {
        Logger.Write(ex,"Exceptions");
        return null;
      }
    }

    #region Utility methods
    private double GetRequestDouble(String keyname)
    {
      if (!(RequestParams == null || 
         string.IsNullOrEmpty(RequestParams[keyname])))
      {
        return Convert.ToDouble(RequestParams[keyname], 
         CultureInfo.InvariantCulture);
      }
      return -1;
    }

    private int GetRequestInt(String keyname)
    {
      if (!(RequestParams == null || 
         string.IsNullOrEmpty(RequestParams[keyname])))
      {
        return Convert.ToInt32(RequestParams[keyname],
          CultureInfo.InvariantCulture);
      }
      return -1;
    }
    #endregion
  }
}

Here comes my little UnityResolver into play, which was described earlier in this blog. What this LayarService basically does is accept a layer name, burp the call into a log file, get the lat, lon, radius, and accuracy from the query string, dump the rest of the query string parameters into a dictionary, use Unity to determine which ILayerProvider implementation is to be loaded, call it’s Get method with the collected data, and return the result.

Now there are only six steps to make this actually work. First, you define a web application project. You reference the LocalJoost.Layar project, System.ServiceModel.dll, System.Runtime.Serialization, every file in the Enterprise Library that starts with "Microsoft.Practices.Unity" (I have 5), and Microsoft.Practices.EnterpriseLibrary.Logging.dll.

The second step is: add a text file to the web application, for instance "LayarService.txt". You enter the following text in it:

<%@ ServiceHost Language="C#" 
    Debug="true" Service="LocalJoost.Layar.LayarService" %>

and rename this the file to "LayerService.svc". The third step is some WCF configuration in the web.config of your web application to host the service as a webHttpBinding, thus making it accept calls via http get:

<services>
  <service name="LocalJoost.Layar.LayarService">
    <endpoint address="" binding="webHttpBinding"
 behaviorConfiguration="WebHttpBehavior"
 contract="LocalJoost.Layar.ILayarService" 
 bindingNamespace="http://whatever/layar">
    </endpoint>
   </service>
</services>
<behaviors>
  <endpointBehaviors>
    <behavior name="WebHttpBehavior">
      <webHttp/>
    </behavior>
  </endpointBehaviors>
</behaviors>

The fourth step is to map your implementations of ILayarProvider to your layers. The LayerService class works in such a way that a layer maps directly to a Unity container, so a configuration might look like this:

<unity>
  <typeAliases>
   <typeAlias alias="ILayarProvider" 
        type="LocalJoost.ILayarProvider,LocalJoost.Layar"/>
   <typeAlias alias="SampleProvider" 
        type="SomeAssembly.SampleProvider,SomeAssembly"/>
   <typeAlias alias="AnotherProvider"
         type="SomeotherAssembly.AnotherProvider, SomeotherAssembly"/>
  </typeAliases>
  <containers>
   <container name="mylayer">
    <types>
     <type type="ILayarProvider" 
     mapTo="SampleProvider"/>
    </types>
   </container>
   <container name="someotherlayer">
    <types>
     <type type="ILayarProvider"
        mapTo="AnotherProvider"/>
    </types>
   </container>
  </containers>
</unity>

Here I have defined two sample containers, thus layers. If, for instance, your service is hosted as “http://mydomain.com/LayarServer/LayerService.svc” you can register your Layer with the Layar developer portal (which is, incidentally, the fifth step) as “http://mydomain.com/LayarServer/LayerService.svc/Layar/mylayer/” (mind the trailing slash!) and the framework will do the rest.

Now the sixth and final step is the real hard part: writing actual implementations of the ILayarProvider. This depends or what you are actually wanting to show. And this it where my help ends ;-).