Kader Yildirim
A la découverte de BizTalk Server 2006 3/3
Développer un assembleur pour BizTalk Server 2006 R2
Par Kader Yildirim publié le 06/05/2008 à 13:20, lu 1165 fois, 6 pages
 3 | Développement de l'assembleur Biztalk
Comme nous venons de le voir la fonction qui est appelée par Biztalk pour traiter les messages dans l'assembleur est Assemble. C'est dans le corps de cette fonction que nous allons tout d'abord mettre à plat les messages à fusionner c'est-à-dire créer un dictionnaire contenant pour chaque identifiant de message (Guid) le message transformé si dans l'orchestration maître on a détecté une sous-orchestration capable de la traiter ou bien le message d'origine s'il n'a pas été changé :

private Dictionary<Guid, Stream> PrepareForParsing()

        {

            Dictionary<Guid, Stream> d = new Dictionary<Guid, Stream>();

            foreach (IBaseMessage bm in _inmsgs)

            {

                if (bm.BodyPartName == r_BodyName)

                {

                    for (int i = 0; i < bm.PartCount; ++i)

                    {

                        string partName = string.Empty;

                        IBaseMessagePart bmp = bm.GetPartByIndex(i, out partName);

                        Guid Name = r_BodyName == partName ? Guid.Empty : new Guid(partName);

                        if (!d.ContainsKey(Name))

                        {

                            Stream s = bmp.GetOriginalDataStream();

                            s.Position = 0;

                            d.Add(Name, s);

                        }

                    }

                }

                else

                {

                    Guid Name = GetInternalName(bm);

                    Stream s = bm.BodyPart.GetOriginalDataStream();

                    s.Position = 0;

                    if (d.ContainsKey(Name))

                        d[Name] = s;

                    else

                        d.Add(Name, s);

                }

            }

 

            return d;

        }

Ensuite nous allons agréger tous « sous-messages » dans le message principal :

private Stream ComposeMessage(Dictionary<Guid, Stream> dvn)

        {

            MemoryStream stream = new MemoryStream();

            using (XmlReader reader = XmlReader.Create(dvn[Guid.Empty]))

            {

                using (XmlWriter writer = XmlWriter.Create(stream))

                {

                    while (reader.Read())

                    {

                        if (reader.NodeType == XmlNodeType.Element &&

                            reader.LocalName == r_TagName)

                        {

                            reader.Read();

                            Guid g = new Guid(reader.Value);

                            if (!dvn.ContainsKey(g))

                            {

                                writer.WriteElementString(r_TagName, g.ToString());

                            }

                            else

                            {

                                using (XmlReader partReader = XmlReader.Create(dvn[g]))

                                {

                                    reader.Read();//read guid end tag

 

                                    do

                                    {

                                        if (partReader.NodeType != XmlNodeType.XmlDeclaration)

                                            PipelineUtils.Util.WriteShallowNode(partReader, writer);

                                    }

                                    while (partReader.Read());

 

                                    dvn[g].Position = 0;

                                }

                            }

                        }

                        else PipelineUtils.Util.WriteShallowNode(reader, writer);

                    }

                }

            }

            stream.Position = 0;

            return stream;

        }

Bien sûr le tout est orchestré depuis la fonction Assemble :

public Microsoft.BizTalk.Message.Interop.IBaseMessage Assemble(Microsoft.BizTalk.Component.Interop.IPipelineContext pc)

        {

            Dictionary<Guid, Stream> dvn = PrepareForParsing();

            IBaseMessageFactory bmf = pc.GetMessageFactory();

            IBaseMessage bm = bmf.CreateMessage();

            bm.AddPart(Guid.Empty.ToString(), BuildMessagePart(bmf, ComposeMessage(dvn), pc), true);

 

            // TODO: implement assembling logic

            // BizTalk 2004 documentation: "In this release of BizTalk Server 2004,

            // assembling functionality is not used, so BizTalk Server always passes

            // one document to the component input."

            return bm;

        }

private IBaseMessagePart BuildMessagePart(IBaseMessageFactory bmf, Stream s, IPipelineContext pc)

        {

            if (null == bmf || null == s)

                return null;

 

            IBaseMessagePart bmp = bmf.CreateMessagePart();

            bmp.Data = s;

            pc.ResourceTracker.AddResource(s);

            bmp.Data.Position = 0;

            return bmp;

        }

Vous noterez au passage l'utilisation du ResourceTracker qui permet à BizTalk de connaître les ressources qu'il doit gérer.
 
» Démarrer une discussion