1

I am registering specific messages that when received call specific events.

I see BrokeredMessage accepts an object, which I understand I would need to implement ISerializable for all messages.

Hpwever, my messages are plain POCO objects, and I would like to explore possibilities of using them as-is:

public class CustomerOrderEvent
{
   int orderId;
   int quantity;
   double value;
}

During receive I would:

  1. Retrieve the message and return to object type
  2. Look-up my map, call events who are registered for this event message

Whilst simple to describe, pulling my hair out with the first step.

Are there any frameworks, that would wrap this for me over the Azure bus?

If using IoC, ideally I would like to have the capability to use my favorite injector SimpleInjector - if it is straight forward to define an adapter this would not be a problem.

morleyc
  • 2,169
  • 10
  • 48
  • 108

1 Answers1

3

At some point you'll have to have a class with DataContract, DataMember, etc, attributes on it to send to a DataContactSerializer. But, you don't have to add them to your POCO.

One option is to simply create a DTO that you populate with the same data as your POCO. This DTO you'd wrap with the BrokeredMessage. Or, you could simply serialize your POCO in some way to a Stream and give that to a BrokeredMessage

An alternative is to use what .NET serialization calls "surrogates" (roughly the same as a DTO). This requires that you not only define the surrogate, but also define IDataContractSurrogate implementation to use when manually creating your DataContractSerializer.

First, I'll assume that what you really have is a POCO with public properties, not the POCO with private fields that you posted. With that you can create a surrogate:

[DataContract(Name = "CustomerOrderEvent", Namespace = "http://www.mynamespace.com")]
public class CustomerOrderEventSurrogate
{
    [DataMember]
    public int OrderId { get; set; }

    [DataMember]
    public int Quantity { get; set; }

    [DataMember]
    public double Value { get; set; }
}

...straightforward, in this example, the same as your POCO with all the necessary attributes. Then you define a IDataContractSurrogate implementation:

public class DataContractSurrogate : IDataContractSurrogate
{
    public Type GetDataContractType(Type type)
    {
        if (typeof (CustomerOrderEvent).IsAssignableFrom(type))
        {
            return typeof (CustomerOrderEventSurrogate);
        }
        return type;
    }

    public object GetObjectToSerialize(object obj, Type targetType)
    {
        var customerOrderEvent = obj as CustomerOrderEvent;
        if (customerOrderEvent == null) return obj;

        var surrogate =
            new CustomerOrderEventSurrogate
                {
                    OrderId = customerOrderEvent.OrderId,
                    Quantity = customerOrderEvent.Quantity,
                    Value = customerOrderEvent.Value
                };
        return surrogate;
    }

    public object GetDeserializedObject(object obj, Type targetType)
    {
        var surrogate = obj as CustomerOrderEventSurrogate;
        if (surrogate == null) return obj;

        var customerOrderEvent =
            new CustomerOrderEvent()
                {
                    OrderId = surrogate.OrderId,
                    Quantity = surrogate.Quantity,
                    Value = surrogate.Value
                };
        return customerOrderEvent;
    }

    public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)
    {
        throw new NotImplementedException();
    }

    public object GetCustomDataToExport(Type clrType, Type dataContractType)
    {
        throw new NotImplementedException();
    }

    public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
    {
        throw new NotImplementedException();
    }

    public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
    {
        throw new NotImplementedException();
    }

    public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit)
    {
        throw new NotImplementedException();
    }
}

Here we throw NotImplementedException for optional methods. This implementation implements GetDataContractType to tell caller that it supports CustomerOrderEvent and to use CustomerOrderEventSurrrogate instead, when serializing. It also implements GetObjectToSerialize and GetDeserializeObject to map back and forth from the surrogate to the POCO.

Now, you just create a BrokeredMessage with a DataContractSerializer instance that knows about the IDataContractSurrogate implementation you want to use. For example:

var customerOrderEvent = new CustomerOrderEvent
                                {
                                    OrderId = 1,
                                    Quantity = 1,
                                    Value = 1.99
                                };

var dataContractSerializer =
    new DataContractSerializer(typeof (CustomerOrderEvent),
                                new[] {typeof (CustomerOrderEvent)},
                                int.MaxValue,
                                true,
                                true,
                                new DataContractSurrogate());

var message = new BrokeredMessage(customerOrderEvent, dataContractSerializer);

And when you receive the message, you can pass the DataContractSerializer object in to the GetBody method. For example:

message.GetBody<CustomerOrderEvent>(dataContractSerializer);

...which presumes this side of the conversation has done all the same things as the other (have the surrogate class, the IDataContractSurrogate implementation, and created the dataContractSerializer properly.)

Peter Ritchie
  • 35,463
  • 9
  • 80
  • 98