|
//*****************************************************************************
// Description.....WF4 Message Mediation Library
//
// Author..........Roman Kiss, rkiss@pathcom.com
// Copyright © 2009 ATZ Consulting Inc. (see included license.rtf file)
//
// Date Created: 07/07/09
//
// Date Modified By Description
//-----------------------------------------------------------------------------
// 07/07/09 Roman Kiss Initial Revision
//
//*****************************************************************************
//
#region Namespaces
using System;
using System.Activities;
using System.Activities.Presentation.PropertyEditing;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Xml.Linq;
#endregion
namespace RKiss.MessageMediationActivityLibrary
{
public sealed class XPathMessageInspector : CodeActivity
{
private IDictionary<string, OutArgument> outputs;
private bool deserializeMessage = false;
#region Properties
[Category("Input")]
[RequiredArgument]
public InArgument<string> XPath { get; set; }
[Category("Input")]
[RequiredArgument]
public InOutArgument<Message> Message { get; set; }
[DefaultValue(null)]
public Dictionary<string, string> Namespaces { get; set;}
[Category("Result")]
[Browsable(true)]
[Editor(typeof(RKiss.MessageMediationActivityLibrary.Editors.DynamicArgumentDictionaryEditor), typeof(PropertyValueEditor))]
public IDictionary<string, OutArgument> Outputs
{
get
{
if (this.outputs == null)
{
this.outputs = new Dictionary<string, OutArgument>();
}
return this.outputs;
}
}
[Browsable(false)]
public string SourceUri { get; set; }
#endregion
public XPathMessageInspector()
{
this.Namespaces = new Dictionary<string, string>();
}
#region Execute
protected override void Execute(CodeActivityContext context)
{
Message message = this.Message.Get(context);
string xpath = this.XPath.Get(context);
object result = null;
this.deserializeMessage = (xpath.IndexOf(":Body") > 0);
// namespaces
PropertyInfo pi = typeof(EnvelopeVersion).GetProperty("Namespace", BindingFlags.Instance | BindingFlags.NonPublic);
string envelopeNamespace = (string)pi.GetValue( message.Version.Envelope, null);
pi = typeof(AddressingVersion).GetProperty("Namespace", BindingFlags.Instance | BindingFlags.NonPublic);
string addressNamespace = (string)pi.GetValue(message.Version.Addressing, null);
XPathMessageContext contextExt = new XPathMessageContext();
contextExt.AddNamespace("s", envelopeNamespace);
contextExt.AddNamespace("a", addressNamespace);
if (this.Namespaces != null)
{
foreach (var param in this.Namespaces)
{
string prefix = param.Key;
string ns = param.Value;
if (string.IsNullOrEmpty(prefix) || string.IsNullOrEmpty(ns)) continue;
contextExt.AddNamespace(prefix, ns);
}
}
bool bIsResult = this.Outputs.ContainsKey("_result");
Type argumentType = bIsResult ? this.Outputs["_result"].ArgumentType : typeof(XPathResult);
Type valueType = argumentType == typeof(string) ? argumentType : typeof(XPathResult);
XPathMessageQuery query = new XPathMessageQuery(xpath, contextExt);
Type type = typeof(XPathMessageQuery);
#region xpath evaluation
if (this.deserializeMessage || message.Version == MessageVersion.None)
{
MethodInfo mi = type.GetMethod("Evaluate", new Type[] { typeof(MessageBuffer) }).MakeGenericMethod(valueType);
// copy message
using (MessageBuffer buffer = message.CreateBufferedCopy(Int32.MaxValue))
{
this.Message.Set(context, buffer.CreateMessage());
result = mi.Invoke(query, new object[] { buffer });
}
}
else
{
MethodInfo mi = type.GetMethod("Evaluate", new Type[] { typeof(Message) }).MakeGenericMethod(valueType);
result = mi.Invoke(query, new object[] { message });
}
#endregion
bool bResultDone = false;
if (result is XPathResult)
{
var xr = result as XPathResult;
if(xr.ResultType == System.Xml.XPath.XPathResultType.Error)
throw new NullReferenceException("XPathResult: the expression doesn't evaluate to the correct XPath type");
if (xr.ResultType == System.Xml.XPath.XPathResultType.NodeSet || xr.ResultType == System.Xml.XPath.XPathResultType.NodeSet)
{
var nav = xr.GetResultAsNodeset();
if (nav == null)
throw new NullReferenceException("XPathResult: Result is not Nodeset");
if (nav.Count == 0)
throw new NullReferenceException(string.Format("XPathResult: No match for '{0}'", xpath));
nav.MoveNext();
if (nav.Current != null && (nav.Current.NodeType == System.Xml.XPath.XPathNodeType.Element || nav.Current.NodeType == System.Xml.XPath.XPathNodeType.Root))
{
var root = XElement.Parse(nav.Current.OuterXml);
if (root == null)
throw new NullReferenceException("XPathResult: Cannot create root XElement from result");
#region all outputs
foreach (var param in this.Outputs)
{
if (bIsResult && param.Key == "_result")
{
if (argumentType == typeof(XElement) || argumentType == typeof(object))
this.Outputs["_result"].Set(context, root);
else if (argumentType == typeof(XPathResult))
this.Outputs["_result"].Set(context, result);
else
{
Type argType = this.Outputs[param.Key].ArgumentType;
string res = (result as XPathResult).GetResultAsString();
if (string.IsNullOrEmpty(res) && argType != typeof(string))
throw new ArgumentNullException("XPathResult: the value is null or empty");
this.Outputs[param.Key].Set(context, Convert.ChangeType(res, argType));
}
bResultDone = true;
}
else if (param.Key == "_root")
{
this.Outputs["_root"].Set(context, root);
}
else
{
var xname = XName.Get(param.Key);
var element = root.Name == xname ? root : root.Element(XName.Get(param.Key));
if (element != null)
{
if (element.HasElements || element.HasAttributes)
this.Outputs[param.Key].Set(context, element);
else
{
Type argType = this.Outputs[param.Key].ArgumentType;
this.Outputs[param.Key].Set(context, argType == typeof(object) ? element.Value : Convert.ChangeType(element.Value, argType));
}
}
}
}
#endregion
}
}
}
if (bIsResult && bResultDone == false)
{
this.Outputs["_result"].Set(context, result);
}
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.