\r
XmlResolver xmlResolver;\r
IntPtr stylesheet;\r
+ Hashtable extensionObjectCache = new Hashtable();\r
\r
#endregion\r
\r
foreach (string ns in extobjects.Keys) {\r
object ext = extobjects[ns];\r
\r
- System.Type type;\r
- System.Collections.IEnumerable methods;\r
+ if (extensionObjectCache.ContainsKey(ext)) {\r
+ foreach (ExtensionFunctionHolder ef in (ArrayList)extensionObjectCache[ext]) {\r
+ int ret = xsltRegisterExtFunction(context, ef.name, ef.ns, ef.func);\r
+ if (ret != 0) throw new XmlException("Could not reregister extension function " + ef.name + " in " + ef.ns);\r
+ }\r
\r
- // As an added bonus, if the extension object is a UseStaticMethods object\r
- // (defined below), then add the static methods of the specified type.\r
- if (ext is UseStaticMethods) {\r
- type = ((UseStaticMethods)ext).Type;\r
- methods = type.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);\r
- ext = null;\r
} else {\r
- type = ext.GetType();\r
- methods = type.GetMethods();\r
- }\r
+ object extsrc;\r
+ \r
+ System.Type type;\r
+ System.Collections.IEnumerable methods;\r
+ \r
+ // As an added bonus, if the extension object is a UseStaticMethods object\r
+ // (defined below), then add the static methods of the specified type.\r
+ if (ext is UseStaticMethods) {\r
+ type = ((UseStaticMethods)ext).Type;\r
+ methods = type.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);\r
+ extsrc = null;\r
+ } else {\r
+ extsrc = ext;\r
+ type = ext.GetType();\r
+ methods = type.GetMethods();\r
+ }\r
+\r
+ ArrayList functionstocache = new ArrayList();\r
+ \r
+ Hashtable alreadyadded = new Hashtable ();\r
+ foreach (System.Reflection.MethodInfo mi in methods) {\r
+ if (alreadyadded.ContainsKey(mi.Name)) continue; // don't add twice\r
+ alreadyadded[mi.Name] = 1;\r
\r
- Hashtable alreadyadded = new Hashtable ();\r
- foreach (System.Reflection.MethodInfo mi in methods) {\r
- if (alreadyadded.ContainsKey(mi.Name)) continue; // don't add twice\r
- alreadyadded[mi.Name] = 1;\r
+ // Simple extension function delegate\r
+ ExtensionFunction func = new ExtensionFunction(new ReflectedExtensionFunction(type, extsrc, mi.Name).Function);\r
+ \r
+ // Delegate for libxslt library call\r
+ libxsltXPathFunction libfunc = new libxsltXPathFunction(new ExtensionFunctionWrapper(func).Function);\r
+ \r
+ int ret = xsltRegisterExtFunction(context, mi.Name, ns, libfunc);\r
+ if (ret != 0) throw new XmlException("Could not register extension function " + mi.DeclaringType.FullName + "." + mi.Name + " in " + ns);\r
\r
- // Simple extension function delegate\r
- ExtensionFunction func = new ExtensionFunction(new ReflectedExtensionFunction(type, ext, mi.Name).Function);\r
+ ExtensionFunctionHolder efh;\r
+ efh.name = mi.Name;\r
+ efh.ns = ns;\r
+ efh.func = libfunc;\r
+ functionstocache.Add(efh);\r
+ }\r
+\r
+ extensionObjectCache[ext] = functionstocache;\r
\r
- // Delegate for libxslt library call\r
- libxsltXPathFunction libfunc = new libxsltXPathFunction(new ExtensionFunctionWrapper(func).Function);\r
- \r
- int ret = xsltRegisterExtFunction(context, mi.Name, ns, libfunc);\r
- if (ret != 0) throw new XmlException("Could not register extension function " + mi.DeclaringType.FullName + "." + mi.Name + " in " + ns);\r
}\r
- \r
+ \r
}\r
\r
result = xsltApplyStylesheetUser(stylesheet, doc, argArr, null, IntPtr.Zero, context);\r
\r
internal delegate object ExtensionFunction(object[] args);\r
\r
+ private struct ExtensionFunctionHolder {\r
+ public libxsltXPathFunction func;\r
+ public string ns, name;\r
+ }\r
+\r
// Wraps an ExtensionFunction into a function that is callable from the libxslt library.\r
private unsafe class ExtensionFunctionWrapper {\r
- ExtensionFunction func;\r
+ private readonly ExtensionFunction func;\r
\r
- public ExtensionFunctionWrapper(ExtensionFunction func) { this.func = func; }\r
- \r
- public unsafe void Function(IntPtr xpath_ctxt, int nargs) {\r
+ public ExtensionFunctionWrapper(ExtensionFunction func) {\r
+ if ((object)func == null) throw new ArgumentNullException("func");\r
+ this.func = func;\r
+ }\r
\r
+ public unsafe void Function(IntPtr xpath_ctxt, int nargs) {\r
// Convert XPath arguments into "managed" arguments\r
System.Collections.ArrayList args = new System.Collections.ArrayList();\r
for (int i = 0; i < nargs; i++) {\r
args.Add( xmlXPathCastToNumber(aptr));\r
else if (aptr->type == 4) // Strings\r
args.Add( xmlXPathCastToString(aptr));\r
- else if (aptr->type == 1) { // Node Sets ==> ArrayList of strings\r
+ else if (aptr->type == 1 && aptr->nodesetptr != null) { // Node Sets ==> ArrayList of strings\r
System.Collections.ArrayList a = new System.Collections.ArrayList();\r
for (int ni = 0; ni < aptr->nodesetptr->count; ni++) {\r
xpathobject *n = xmlXPathNewNodeSet(aptr->nodesetptr->nodes[ni]);\r
xmlXPathFreeObject(aptr);\r
}\r
\r
- // Call function\r
args.Reverse();\r
+\r
object ret = func(args.ToArray());\r
\r
// Convert the result back to an XPath object\r
if (ret == null) // null => ""\r
valuePush(xpath_ctxt, xmlXPathNewCString(""));\r
- else if (ret is Boolean) // Booleans\r
+ else if (ret is bool) // Booleans\r
valuePush(xpath_ctxt, xmlXPathNewBoolean((bool)ret ? 1 : 0));\r
else if (ret is int || ret is long || ret is double || ret is float || ret is decimal)\r
// Numbers\r
valuePush(xpath_ctxt, xmlXPathNewFloat((double)ret));\r
- else // Strings\r
+ else // Everything else => String\r
valuePush(xpath_ctxt, xmlXPathNewCString(ret.ToString()));\r
\r
}\r
public ReflectedExtensionFunction(System.Type type, object src, string methodname) { this.type = type; this.src = src; this.methodname = methodname; }\r
\r
public object Function(object[] args) {\r
- // Construct arg type array, stringified version in case of problem\r
+ // Construct arg type array, and a stringified version in case of problem\r
System.Type[] argtypes = new System.Type[args.Length];\r
string argtypelist = null;\r
for (int i = 0; i < args.Length; i++) {\r
// No method?\r
if (mi == null) throw new XmlException("No applicable function for " + methodname + " takes (" + argtypelist + ")");\r
\r
+ if (!mi.IsStatic && src == null) throw new XmlException("Attempt to call static method without instantiated extension object.");\r
+\r
// Invoke\r
return mi.Invoke(src, args);\r
}\r