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.)