Living in the Tech Avalanche Generation

A practitioner’s introspective on technology

Archive for the 'C#' Category

GOF Series: Episode #3 [The Singleton - aka the devils work]

Next in the series we continue with the creational group of patterns and move onto the singleton pattern.

What is the singleton and how does it work?

  • A globally available single instance of class, where only one single instance can exist at any given point in time.
  • Maintains and instantiates itself across multiple threads at any given time.
  • All public methods and members are accessed via the single instance.
  • Constructed instances cannot be created outside of the singleton class. This is achieved by using a private constructor only accessible from the singleton itself.

Is the singleton the devils work?

  • They promote tight coupling between objects and components – consumers know exactly where to get a copy of their collaborating classes.
    • Remember that coupling is a measure of dependencies.
  • Cannot be easily substituted ala dependency injection.
  • Inherently lack scale.
  • Difficult to unit test.

Singleton example in C#

Given this singleton below:

public sealed class Singleton
{
    static Singleton _instance = null;
    static readonly object _padlock = new object();
    static List<int> _ThreadSafeCounterList = new List<int>();
    static readonly Guid _instanceId = Guid.NewGuid();

    private Singleton() { }

    public static Singleton Instance
    {
        get
        {
            lock (_padlock)
            {
                if (_instance == null)
                {
                    _instance = new Singleton();
                }
                return _instance;
            }
        }
    }

    public List<int> ThreadSafeCounterList
    {
        get
        {
            lock (_padlock)
            {
                return Singleton._ThreadSafeCounterList;
            }
        }
        set
        {
            lock (_padlock)
            {
                Singleton._ThreadSafeCounterList = value;
            }
        }
    }

    public Guid ID
    {
        get { return _instanceId; }
    }
}

and this program:

class Program
{
    static AutoResetEvent evt;

    static void Main(string[] args)
    {
        Console.WriteLine(“Enter a key to begin the singleton workers”);
        Console.ReadLine();
        const int countup = 2000;
        for (int x = 0; x <= countup; x++)
        {
            //new up a background worker
            BackgroundWorker bg = new BackgroundWorker();
            //wire up the work handler delegate to do the computation
            bg.DoWork += new DoWorkEventHandler(bg_DoWork);
            //when x has reach the upper boundary of the loop
            //subscribe to the event that fires when the
            //work handler has completed its work (will subscribe)
            //to the last thread dialled up via the bg worker
            if (x == countup)
            {
                //last bg worker thread - subscribed to its 
                //completed event to signal an end
                bg.RunWorkerCompleted +=
                    new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
            }
            //run up a thread
            bg.RunWorkerAsync(x);
        }
        //wait until blocks the current thread (main thread)
        //until signaled - will pause here..
        evt = new AutoResetEvent(false);
        evt.WaitOne();
    }

    static void bg_RunWorkerCompleted(object sender,
        RunWorkerCompletedEventArgs e)
    {
        Console.WriteLine(“Start reading of the list in “ +
            “the order the items were written.”);
        Console.ReadLine();

        //loop the list of integers and print 
        //them in order they were inserted
        for (int i = 0; i < Singleton.Instance.
            ThreadSafeCounterList.Count; i++)
        {
            Console.WriteLine(Singleton.Instance.
                ThreadSafeCounterList[i].ToString());
        }

        //signal to the user the total processing figures
        Console.WriteLine(“TOTAL added to Thread safe List is : “ +
            Singleton.Instance.ThreadSafeCounterList.Count.ToString());

        //pause for user entry
        Console.ReadLine();

        //signal to the main thread to continue
        //and therefore exit.
        evt.Set();
    }

    static void bg_DoWork(object sender, DoWorkEventArgs e)
    {
        System.Threading.Thread.Sleep(10);

        Console.WriteLine(“Added “ + e.Argument.ToString() +
            ” by thread with hashcode “ + Thread.CurrentThread.GetHashCode() +
            “\tto instance ID:\t” + Singleton.Instance.ID.ToString());

        //add the integer to the list
        Singleton.Instance.ThreadSafeCounterList.Add((int)e.Argument);

        //give back a time slice so the other threads get a piece
        System.Threading.Thread.Sleep(10);

        //write out to the window when you find 
        //the same integer that was just added
        //because a time slice was given back to
        //the OS task scheduler, another thread
        //may be processing, so the found integer 
        //and thread hashcode will not necessarily
        //print in order.
        Console.WriteLine(“Found “ + Singleton.Instance.
            ThreadSafeCounterList.Find(
            delegate(int findInt)
            {
                if (findInt == (int)e.Argument)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }).ToString()
                + ” by thread with hashcode “ +
                Thread.CurrentThread.GetHashCode() +
                “\tto instance ID:\t” +
                Singleton.Instance.ID.ToString());
    }
}

We have a program that will count up to 2,000 and use a thread safe singleton to insert and read those 2,000 counters. Each iteration will fire off a new background worker thread to do the work of both the insert and read of each of the iterations counter. Whilst this program serves no useful function, it represents an example of a thread safe singleton where data is shared and accessed in both read and volatile writes concurrently.

Next up

Next up in the series will the prototype pattern and I am going to try and include it with an IronRuby example as well as in C#. The entire Patterns series code and PowerPoint presentation can be downloaded here.

Share/Save/Bookmark

No comments

POCO improves inheritance for LINQ to SQL

Have you ever needed to use inheritance with LINQ To SQL? The designer experience isn’t exactly what your OO professor probably had in mind when it comes to modelling inheritance and to honest the whole process feels wrong. Let me explain.

I don’t like the whole ‘partial’ class approach to inheritance to begin with. I want the freedom to inherit without the need for using Partial classes and better still I don’t want my business objects to be tied to the LINQ To SQL platform. If we consider the following scenario where my LINQ To SQL designer experience looks like this:

Figure 1.0

L2SDesigner

What figure 1.0 demonstrates is the we have an employee entity, from which three other entities all inherit. SalaryEmployee, CommissionEmployee and ContractEmployee all have employee as their base class. In the case of SalaryEmployee, it distinctly encapsulates a property for the middle initial via the property ‘minit’. Sure the designer looks great but from the perspective of the code, the designer has generated things don’t look so nice to me, as demonstrated in the following code listing.

Code Listing 1.0

[Table(Name="dbo.employee")]
[InheritanceMapping(Code="1", Type=typeof(SalaryEmployee)]
[InheritanceMapping(Code="2", Type=typeof(CommissionEmployee))]
[InheritanceMapping(Code="3", Type=typeof(ContractEmployee))]
public partial class employee : INotifyPropertyChanging,
                                INotifyPropertyChanged
{
    //…….
}

public partial class SalaryEmployee : employee
{
    private System.Nullable<char> _minit;

    #region Extensibility Method Definitions

    partial void OnLoaded();
    partial void OnValidate(System.Data.Linq.ChangeAction action);
    partial void OnCreated();
    partial void OnminitChanging(System.Nullable<char> value);
    partial void OnminitChanged();

    #endregion

    public SalaryEmployee()
    {
        OnCreated();
    }

    [Column(Storage="_minit", DbType="Char(1)")]
    public System.Nullable<char> minit
    {
        get
        {
            return this._minit;
        }
        set
        {
            if ((this._minit != value))
            {
                this.OnminitChanging(value);
                this.SendPropertyChanging();
                this._minit = value;
                this.SendPropertyChanged("minit");
                this.OnminitChanged();
            }
        }
    }
}

public partial class CommissionEmployee: employee
{
    //…….
}

public partial class ContractEmployee: employee
{
    //…….
}

As demonstrated above, the designer generates code that comes decorated with quite a bit of LINQ To SQL infrastructure attributes or noise as I like to call it, along with some partial methods that developers can implement in their own partial classes designed to extend those generated by the designer. I have included the entire code generated for the SalaryEmployee entity for the sake of demonstration and to show that further LINQ To SQL infrastructure code has been used to decorate the entity. Now it’s very important to point out here, that this code should NOT be touched in the IDE and it’s linked inextricably to the designer, so if I just start to add polymorphic behaviours or new members to the entities via the generated code, then the moment I refresh or add anything via the designer, it will blow away any changes made by directly to the code. Microsoft have designed the entity classes in a such a way that by using partial classes we can implement a subsequent file to that provided by the code generator and implement all of our new behaviours and members using our own hand rolled partial class. I could do something like this:

Code Listing 2.0

public interface IEmployee
{
    bool QualifiesAsPrefered();
}

public partial class employee : IEmployee
{
    #region IEmployee Members

    public virtual bool QualifiesAsPrefered()
    {
        return false;
    }

    #endregion
}

I could create this code above in a new code file and thus extend my designer generated entities by using an interface to describe any polymorphic intent against my partial class. This does begin to become unwieldy in my opinion and I consider the use of the partial class a bit of code smell to be blunt and its really only required because of the need to maintain synchronicity between the code generated entity and the designer.

Now this is not to say that developers should not use the designer and take the approach just demonstrated, in fact I should point out that given the right circumstances, such an approach is completely justified. Lets say you work for a small or medium sized project driven business and there is a need to write a data driven application that contains less than significant business logic, has low support requirements, a small user audience and is required in the shortest amount of time possible. Sounds familiar right! Well those are typical times when you might want to do just that. However, what about if I have a team of 6 - 8 developers on a project spanning eight months and the application is driven heavily by data? This is the kind of circumstance that this approach just wont feel comfortable and will cause you headaches because it’s not particularly reusable or portable across a large team, it also leads to business entities getting tied to a Data Access strategy and will have the developer team dragging around all that infrastructure code with them. What is this going to mean for sharing entities within services or what are my serialisation concerns and should I consider breaking my partial classes into separate projects and…….you can see where this is leading, more confusion and pain for all. So what’s the solution?

By using a POCO (Plain Old CLR Object) approach (see DDD) along with LINQ To SQL mapping, we can choose to use our tried and trusted OO skills to describe our classes (entities), cutting down on the number of artifacts it takes to achieve that and in so doing simplify our lives by making the code less ambiguous. So how different would that be? Lets start with the mapping file used to map entities to tables in the database.

Code Listing 3.0


<Database Name="Northwind"
    xmlns="http://schemas.microsoft.com/linqtosql/mapping/2007">
  <Table Name="Customers" Member="Customer">
    <Type Name="Org.TechAvalanche.Orm.Tests.Domain.Customer">
      <Column Name="CustomerID" Member="CustomerID"
        DbType="NChar(5)
            NOT NULL" IsPrimaryKey="true"
        CanBeNull="false" UpdateCheck="Never" />
      <Column Name="CompanyName" Member="CompanyName"
        DbType="NVarChar(40)
            NOT NULL"
        CanBeNull="false" UpdateCheck="Never" />
      <Column Name="ContactName" Member="ContactName"
        DbType="NVarChar(30)"
        CanBeNull="true" UpdateCheck="Never" />
      <Column Name="ContactTitle" Member="ContactTitle"
        DbType="NVarChar(30)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="Address" Member="Address"
        DbType="NVarChar(60)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="City" Member="City"
        DbType="NVarChar(15)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="Region" Member="Region"
        DbType="NVarChar(15)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="PostalCode" Member="PostalCode"
        DbType="NVarChar(10)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="Country" Member="Country"
        DbType="NVarChar(15)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="Phone" Member="Phone"
        DbType="NVarChar(24)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="Fax" Member="Fax"
        DbType="NVarChar(24)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="CustType" Member="CustomerType"
        DbType="Int" CanBeNull="false" IsDiscriminator="true"
        UpdateCheck="Never" />
      <Association Name="Customer_Order"
        Member="Orders" OtherKey="CustomerID" />

      <!– These Two Elements used for inheritance –>
      <Type
        Name="Org.TechAvalanche.Orm.Tests.Domain.InternalCustomer"
        InheritanceCode="1" IsInheritanceDefault="true"/>
      <Type
        Name="Org.TechAvalanche.Orm.Tests.Domain.ExternalCustomer"
        InheritanceCode="2" IsInheritanceDefault="false"/>
    </Type>
  </Table>
  <Table Name="Orders" Member="Order">
    <Type Name="Org.TechAvalanche.Orm.Tests.Domain.Order">
      <Column Name="OrderID" Member="OrderID"
        DbType="Int NOT NULL
            IDENTITY" IsPrimaryKey="true"
        IsDbGenerated="true" CanBeNull="false"
        UpdateCheck="Never" />
      <Column Name="CustomerID" Member="CustomerID"
        DbType="NChar(5)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="EmployeeID" Member="EmployeeID"
        DbType="Int" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="OrderDate" Member="OrderDate"
        DbType="DateTime" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="RequiredDate" Member="RequiredDate"
        DbType="DateTime" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="ShippedDate" Member="ShippedDate"
        DbType="DateTime" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="ShipVia" Member="ShipVia"
        DbType="Int" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="Freight" Member="Freight"
        DbType="Money" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="ShipName" Member="ShipName"
        DbType="NVarChar(40)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="ShipAddress" Member="ShipAddress"
        DbType="NVarChar(60)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="ShipCity" Member="ShipCity"
        DbType="NVarChar(15)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="ShipRegion" Member="ShipRegion"
        DbType="NVarChar(15)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="ShipPostalCode" Member="ShipPostalCode"
        DbType="NVarChar(10)" CanBeNull="true"
        UpdateCheck="Never" />
      <Column Name="ShipCountry" Member="ShipCountry"
        DbType="NVarChar(15)" CanBeNull="true"
        UpdateCheck="Never" />
      <Association Name="Order_OrderLine" Member="OrderLines"
        OtherKey="OrderID" />
      <Association Name="Customer_Order" Member="Customer"
        ThisKey="CustomerID" IsForeignKey="true" />
    </Type>
  </Table>
  <Table Name="[Order Details]" Member="OrderLine">
    <Type Name="Org.TechAvalanche.Orm.Tests.Domain.OrderLine">
      <Column Name="OrderID" Member="OrderID"
        DbType="Int NOT NULL" IsPrimaryKey="true"
        CanBeNull="false" UpdateCheck="Never" />
      <Column Name="ProductID" Member="ProductID"
        DbType="Int NOT NULL" IsPrimaryKey="true"
        CanBeNull="false" UpdateCheck="Never" />
      <Column Name="UnitPrice" Member="UnitPrice"
        DbType="Money NOT
            NULL" CanBeNull="false"
        UpdateCheck="Never" />
      <Column Name="Quantity" Member="Quantity"
        DbType="SmallInt
            NOT NULL" CanBeNull="false"
        UpdateCheck="Never" />
      <Column Name="Discount" Member="Discount"
        DbType="Real NOT
            NULL" CanBeNull="false"
        UpdateCheck="Never" />
      <Association Name="Order_OrderLine" Member="Order"
        ThisKey="OrderID" IsForeignKey="true" />
    </Type>
  </Table>
</Database>

The two entries above that sit directly beneath the comment highlighted in large font demonstrate how to set up mapping XML for regular DotNet CLR objects that are NOT generated by the designer and account for inheritance. The entity code to go with this mapping follows below.

Code Listing 4.0

interface ICustomerData
{
    string Address { get; set; }
    string City { get; set; }
    string CompanyName { get; set; }
    string ContactName { get; set; }
    string ContactTitle { get; set; }
    string Country { get; set; }
    string CustomerID { get; set; }
    string Fax { get; set; }
    IList<Order> Orders { get; set; }
    string Phone { get; set; }
    string PostalCode { get; set; }
    string Region { get; set; }
    int CustomerType { get; set; }
}

public interface ICustomerLoyaltyDiscount
{
    void LoyaltyDiscount();
}

interface ICustomer : ICustomerData, ICustomerLoyaltyDiscount { }

public class Customer : ICustomer
{
    public void LoyaltyDiscount()
    {
        foreach (Order o in Orders)
        {
            o.Freight = 0M;
        }
    }
}

public class InternalCustomer : Customer
{
    //………etc
} 

public class ExternalCustomer : Customer
{
    //………etc
}

If you really must have a designer to view and work with your entities then it’s no sweat to create a class diagram in VS.Net and enjoy a similar design experience as you would with the LINQ To SQL designer however enjoy the benefits of going POCO at the same time.

Figure 2.0

classDesigPoco

The consumer code would look something like this:

public void SimpleRepositoryFetchingStrategyTest()
{
    Specification<Customer> simonsCoSpec =
        new Specification<Customer>
        (c => c.Country == "Germany");

    DataContext ctx = GetContext();

    Repository<Customer> customerRepository =
        new Repository<Customer>(ctx);

    CustomerLoyaltyDiscountFetchingStrategy strategy =
        new CustomerLoyaltyDiscountFetchingStrategy();

    var custs = customerRepository.All(simonsCoSpec, strategy);

    foreach (var cust in custs)
    {
        cust.LoyaltyDiscount();
        Console.WriteLine("The Name of the Customer " +
            "from Germany is {0}", cust.CompanyName);
        foreach (var order in cust.Orders)
        {
            Console.WriteLine("\tOrder Number {0}",
                order.OrderID);
            foreach (var orderLine in order.OrderLines)
            {
                Console.WriteLine("\t\tProduct ID {0} Amount {1}",
                        orderLine.ProductID,
                        (orderLine.Quantity * orderLine.UnitPrice));
            }
        }
    }
}
private static DataContext GetContext()
{
    //get a stream reader from the mapping file

    StreamReader sr =
        new StreamReader(@"D:\Mapping\DomainMapping.xml");

    //set the mapping source up
    XmlMappingSource mapping =
        XmlMappingSource.FromStream(sr.BaseStream);

    DataContext db = null;

    //new up a persistance repository
    db = new DataContext
        ("server=localhost;initial catalog=Northwind;" +
        "user id=sa;password=mrbig", mapping);

    return db;
}

I will shortly be posting a framework that makes working in a POCO and DDD style much simpler. The Framework includes implemented Specification Patterns, Fetching Strategies and Extensible Repositories for your LINQ To SQL pleasure.

Share/Save/Bookmark

1 comment

Lesser coupled WCF Services.

I hear people talk about how WCF or ASMX services are inherently loosely coupled by default out of the box, whether they use HTTP or TCP or any old transport available for that matter. “Just use Web Services or WCF and you get loose coupling for free” they say. So the story of temporal coupling using Web Services is well known now as are the many issues with platform coupling and indeed the solution below does not address platform coupling directly as it leans on XML to manage serialization. The coupling that I am interested in addressing here is that created by dependency to the ubiquitous proxy or WSDL contract. Lets examine this a little more closely.

The Reason:

The most common method for a consumer of a service (WCF / ASMX) to maintain and manage the resolution to it’s interface is WSDL. This requires each consumer having to carry around the contract with it, forever in it’s servitude to understand the mysteries that lie at the boundary of it’s faithful service. So without this proxy I don’t know what message to send and where to send it (and yes I know you don’t have to use WSDL and you can proxy off the interface - but that leaves us still coupled to the service interface). Coupling is a measure of dependency and because our consumer depends rather heavily on the service interface or WSDL it is quite squarely coupled to it. Version control with WSDL isn’t trivial to manage and so the coupling story gets worse when we want to change the interface. WCF does provide some methods to relax this versioning problem by ignoring parts of messages from old contract consumers however this is still not adequate. We also hit the coupling ceiling when you consider that all my endpoints are bound to particular message types with respect to the message sent and returned. More recently prescribed guidance has suggested a pattern in sending more coarsely grained messages that are less chatty by utilising complex types or [DataContract] in the world of WCF, but unfortunately I’m still coupled to the schema of these big messages.

How to address this?

One way of addressing this would be to provide blandly consistent service interfaces that never change and utilise the most generic of all messages - System.ServiceModel.Channels.Message, otherwise known as an untyped message in WCF. We can bundle up our rich business messages (as serialized POCO’s) and send them in the body of the untyped message. Once having arrived at our bland endpoint, we could check for an appropriate handler of this message (POCO). What’s required is to de-serialize XML out of the body of our untyped message and back into a POCO and then have the handler manage the message for which it was built to handle. Below is a really rudimentary way of thinking about this interaction.

messageAndHandler

The Code for sending the message could look something like this:

public void ExampleSend()
{
    //create a channel to the BUS
    EndpointAddress address =
        new EndpointAddress
            (“net.tcp://localhost:9002/Org.ItResults.” +
            “Soa.Hosts.HumanResourceServiceSvc”);

    NetTcpBinding binding =
        new NetTcpBinding
        { SendTimeout = new TimeSpan(0, 10, 0) };
    ChannelFactory<IEndpoint> factory =
        new ChannelFactory<IEndpoint>(binding, address);
    IEndpoint channel = factory.CreateChannel();

    TestMessage tm = new TestMessage(Guid.NewGuid());

    XmlReader reader = Serializator.SerializeMessage(tm);

    //Create the Message to put on the BUS
    //with the serialized data contract embedded
    //into its body and the target method
    //at the endpoint for the BUS channel
    Message msg = Message.CreateMessage(
        binding.MessageVersion,
        “urn:BaseEndpoint-Recieve”, reader);

    //send the message onto the BUS
    channel.Recieve(msg);

    //Close the comms
    factory.Close();
}

On the receiving side the code might look like the following:

public void TestReceive(Message msg)
{
    //NOTE: the types of T handlers could be
    //loaded into the host process

    //a library where an appropriate
    //set of handler might be located
    const string path =
        @”D:\LocalWorking\ITResults\” +
        “Org.ItResults.ServiceOriented.System” +
        @”\Org.ItResults.Soa.Poc.Messages\bin\debug“;

    //get all the types in the path that have
    //generic args. They may be Message Handlers
    //for messages (the generic args)
    List<Type> generics =
        GenericTypeReader
        .InterfaceTypesInPathWithGenericArgs(path);

    List<object> unravelled = new List<object>();

    //for each type found with a generic arg
    //try to deserialize the body of the message
    //in the endpoints method arg into each
    //generic type found
    generics.ForEach(t =>
        unravelled.Add
        (Serializator.DeserializeMessage(msg, t)));

    unravelled.ForEach(delegate(object o)
    {
        //find a handler for the deserialized object
        IMessageHandler handler;
        handler = GenericTypeReader.
            FindHandlerForMessageTypeInPath<IMessageHandler>
            (path, o.GetType());

        handler.GetType().
            GetMethod(”HandleMessage”)
            .Invoke(handler,
            new[] { o });
    });
}

Where a message handler looks something like:

public interface IMessageHandler { }

public interface IResponseMessageHandler<T> :
    IMessageHandler where T : IMessage
{
    /// <summary>
    /// Handles messages that are not required
    /// to return a response.
    /// </summary>
    /// <param name=”message”>
    /// The type of message to handle.
    /// </param>
    Message HandleMessage(T message);
}

public interface IOneWayMessageHandler<T> :
    IMessageHandler where T : IMessage
{
    /// <summary>
    /// Handles messages that are not required
    /// to return a response.
    /// </summary>
    /// <param name=”message”>
    /// The type of message to handle.
    /// </param>
    void HandleMessage(T message);
}

And finally the message and it’s concrete handler might look like this:

public interface IMessage
{
    Guid ID { get; }
}

[XmlRoot(Namespace = "Org.ItResults.com.au")]
public class TestMessage : IMessage
{
    private Guid _id;
    private string _nameofMEssage;

    #region IMessage Members

    [XmlElement(Order = 1)]
    public Guid ID
    {
        get { return _id; }
        set { _id = value; }
    }

    #endregion

    public TestMessage() { }

    public TestMessage(Guid id)
    {
        _id = id;
    }

    [XmlElement(Order = 2)]
    public string NameOfMessage
    {
        get { return “Test Message”; }
        set { _nameofMEssage = value; }
    }
}

public class TestHandler :
    IOneWayMessageHandler<TestMessage>
{
    #region IMessageHandler Members

    public void HandleMessage(TestMessage message)
    {
        Console.WriteLine(“The Test Message name was “ +
            “{0} and it’s ID is {1}”,
            message.NameOfMessage, message.ID);
    }

    #endregion
}

It’s evident from the code that I should be able to drop message handlers (contained in libraries) in a library folder close to my service and give that service the ability to handle messages defined by handlers in those libraries. This is very similar to how nServiceBus deals with declaring how a service defines what messages it handles and I have adapted the idea to fit with WCF, which affords us the following:

  1. Decouple from any WSDL proxy and it’s associated versioning issues.
  2. Proxies are now managed via a consistent interface less likely to ever require change, as messages pass in the body of an untyped message.
  3. Release newer versions of message handlers to services without rebuilding against them or  any newly refreshed proxy definition.
  4. Freedom from carrying around WSDL.
  5. No coupling to API CRUD styled service endpoints.
    • This is where the style of using Handlers becomes important. Developers are not required to understand an RPC styled API that describes how to affect the state of underlying data, which more often than not is the legacy found in default Web Service Architecture.

It’s also worth noting that the code above does not list how to deal with return messages contained in the untyped message body of an IResponseMessageHandler<T>. This would be managed in a similar fashion to discovering the correct handlers at the service endpoint, by attempting to deserialize messages into available handlers.

Something that is missing in this example is the ability to do publish and subscribe. Some of my colleagues and I are working on a proof of concept framework that extends the concept demonstrated in this post and will include how to handle Pub / Sub (no duplex channels), endpoint discovery via PNRP and durable messaging using queues (Service Broker Queues).

Share/Save/Bookmark

1 comment

« Previous PageNext Page »

Creative Commons Attribution-ShareAlike 2.5 Australia
Creative Commons Attribution-ShareAlike 2.5 Australia