est-il possible de configurer un sérialiseur Xml alternatif tel que DataContractSerializer de la BCL?
Oui, c'est certainement possible. Nous utilisons le DataContractSerializer
pour certains de nos services. Pour que cela fonctionne, vous devez implémenter l'interface IMessageSerialzer
, qui effectue le travail, puis enregistrez ce sérialiseur avec NServiceBus pendant la chaîne de méthode NServiceBus.Configure
.
Voici le code pour le sérialiseur de message. C'est assez simple.
public class WcfMessageSerializer : IMessageSerializer
{
private readonly IList<Type> knownTypes = new List<Type>();
public IList<Type> MessageTypes
{
get { return knownTypes; }
set
{
knownTypes.Clear();
foreach (var type in value)
{
if (!type.IsInterface && typeof(IMessage).IsAssignableFrom(type)
&& !knownTypes.Contains(type))
{
knownTypes.Add(type);
}
}
}
}
public void Serialize(IMessage[] messages, Stream stream)
{
var xws = new XmlWriterSettings
{
ConformanceLevel = ConformanceLevel.Fragment
};
using (var xmlWriter = XmlWriter.Create(stream, xws))
{
var dcs = new DataContractSerializer(typeof(IMessage), knownTypes);
foreach (var message in messages)
{
dcs.WriteObject(xmlWriter, message);
}
}
}
public IMessage[] Deserialize(Stream stream)
{
var xrs = new XmlReaderSettings
{
ConformanceLevel = ConformanceLevel.Fragment
};
using (var xmlReader = XmlReader.Create(stream, xrs))
{
var dcs = new DataContractSerializer(typeof(IMessage), knownTypes);
var messages = new List<IMessage>();
while (false == xmlReader.EOF)
{
var message = (IMessage)dcs.ReadObject(xmlReader);
messages.Add(message);
}
return messages.ToArray();
}
}
}
Pour brancher ce, vous pouvez utiliser une méthode d'extension telles que les suivantes:
public static class ConfigureWcfSerializer
{
public static Configure WcfSerializer(this Configure config)
{
var messageTypes = Configure.TypesToScan
.Where(t => typeof(IMessage).IsAssignableFrom(t))
.ToList();
config.Configurer
.ConfigureComponent<WcfMessageSerializer>(ComponentCallModelEnum.Singleton)
.ConfigureProperty(ms => ms.MessageTypes, messageTypes);
return config;
}
}
Ce serait invoqué lorsque vous configurez NServiceBus comme ceci:
NServiceBus.Configure
// Other configuration...
.WcfSerializer()
// Other configuration...
.CreateBus()
.Start();
I Vous savez que la sérialisation Xml est prise en charge dans le type NServiceBus.Serializers.XML.MessageSerializer. La raison pour laquelle nous voulions aller avec IEnumerable était que nos messages seraient immuables (Notez les ensembles privés dans les propriétés). Si j'utilise un tableau, les messages ne sont plus immuables car je peux modifier un élément de tableau en utilisant l'indexeur et en remplaçant l'élément existant par un nouvel élément. Comme vous le faites remarquer l'évaluation retardée avec IEnumerable est un problème. Merci Pat – pmcgrath
@pmcgrath: Je me suis battu avec l'argument mutable/immutable tout entier, mais je suis arrivé à la conclusion que cela n'aurait pas d'importance si vos messages sont modifiables car ils ne devraient pas être vos objets de domaine. Le récepteur doit prendre le message et le reconstruire en une entité de domaine qui est pertinente pour la ou les tâches qu'il est sur le point de préformer. –
Cela semble être un problème avec une propriété Collection sans setter également, que XmlSerializer prend en charge. –
TrueWill