Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / XmlUtils / System / Xml / Xsl / Runtime / XmlExtensionFunction.cs / 1305376 / XmlExtensionFunction.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Xml; using System.Xml.Schema; using System.Reflection; using System.Globalization; using System.Diagnostics; namespace System.Xml.Xsl.Runtime { using Res = System.Xml.Utils.Res; ////// Table of bound extension functions. Once an extension function is bound and entered into the table, future bindings /// will be very fast. This table is not thread-safe. /// internal class XmlExtensionFunctionTable { private Dictionarytable; private XmlExtensionFunction funcCached; public XmlExtensionFunctionTable() { this.table = new Dictionary (); } public XmlExtensionFunction Bind(string name, string namespaceUri, int numArgs, Type objectType, BindingFlags flags) { XmlExtensionFunction func; if (this.funcCached == null) this.funcCached = new XmlExtensionFunction(); // If the extension function already exists in the table, then binding has already been performed this.funcCached.Init(name, namespaceUri, numArgs, objectType, flags); if (!this.table.TryGetValue(this.funcCached, out func)) { // Function doesn't exist, so bind it and enter it into the table func = this.funcCached; this.funcCached = null; func.Bind(); this.table.Add(func, func); } return func; } } /// /// This internal class contains methods that allow binding to extension functions and invoking them. /// internal class XmlExtensionFunction { private string namespaceUri; // Extension object identifier private string name; // Name of this method private int numArgs; // Argument count private Type objectType; // Type of the object which will be searched for matching methods private BindingFlags flags; // Modifiers that were used to search for a matching signature private int hashCode; // Pre-computed hashcode private MethodInfo meth; // MethodInfo for extension function private Type[] argClrTypes; // Type array for extension function arguments private Type retClrType; // Type for extension function return value private XmlQueryType[] argXmlTypes; // XmlQueryType array for extension function arguments private XmlQueryType retXmlType; // XmlQueryType for extension function return value ////// Constructor. /// public XmlExtensionFunction() { } ////// Constructor (directly binds to passed MethodInfo). /// public XmlExtensionFunction(string name, string namespaceUri, MethodInfo meth) { this.name = name; this.namespaceUri = namespaceUri; Bind(meth); } ////// Constructor. /// public XmlExtensionFunction(string name, string namespaceUri, int numArgs, Type objectType, BindingFlags flags) { Init(name, namespaceUri, numArgs, objectType, flags); } ////// Initialize, but do not bind. /// public void Init(string name, string namespaceUri, int numArgs, Type objectType, BindingFlags flags) { this.name = name; this.namespaceUri = namespaceUri; this.numArgs = numArgs; this.objectType = objectType; this.flags = flags; this.meth = null; this.argClrTypes = null; this.retClrType = null; this.argXmlTypes = null; this.retXmlType = null; // Compute hash code so that it is not recomputed each time GetHashCode() is called this.hashCode = namespaceUri.GetHashCode() ^ name.GetHashCode() ^ ((int) flags << 16) ^ (int) numArgs; } ////// Once Bind has been successfully called, Method will be non-null. /// public MethodInfo Method { get { return this.meth; } } ////// Once Bind has been successfully called, the Clr type of each argument can be accessed. /// Note that this may be different than Method.GetParameterInfo().ParameterType. /// public Type GetClrArgumentType(int index) { return this.argClrTypes[index]; } ////// Once Bind has been successfully called, the Clr type of the return value can be accessed. /// Note that this may be different than Method.GetParameterInfo().ReturnType. /// public Type ClrReturnType { get { return this.retClrType; } } ////// Once Bind has been successfully called, the inferred Xml types of the arguments can be accessed. /// public XmlQueryType GetXmlArgumentType(int index) { return this.argXmlTypes[index]; } ////// Once Bind has been successfully called, the inferred Xml type of the return value can be accessed. /// public XmlQueryType XmlReturnType { get { return this.retXmlType; } } ////// Return true if the CLR type specified in the Init() call has a matching method. /// public bool CanBind() { MethodInfo[] methods = this.objectType.GetMethods(this.flags); bool ignoreCase = (this.flags & BindingFlags.IgnoreCase) != 0; StringComparison comparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; // Find method in object type foreach (MethodInfo methSearch in methods) { if (methSearch.Name.Equals(this.name, comparison) && (this.numArgs == -1 || methSearch.GetParameters().Length == this.numArgs)) { // Binding to generic methods will never succeed if (!methSearch.IsGenericMethodDefinition) return true; } } return false; } ////// Bind to the CLR type specified in the Init() call. If a matching method cannot be found, throw an exception. /// public void Bind() { MethodInfo[] methods = this.objectType.GetMethods(this.flags); MethodInfo methMatch = null; bool ignoreCase = (this.flags & BindingFlags.IgnoreCase) != 0; StringComparison comparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; // Find method in object type foreach (MethodInfo methSearch in methods) { if (methSearch.Name.Equals(this.name, comparison) && (this.numArgs == -1 || methSearch.GetParameters().Length == this.numArgs)) { if (methMatch != null) throw new XslTransformException(/*[XT_037]*/Res.XmlIl_AmbiguousExtensionMethod, this.namespaceUri, this.name, this.numArgs.ToString(CultureInfo.InvariantCulture)); methMatch = methSearch; } } if (methMatch == null) { methods = this.objectType.GetMethods(this.flags | BindingFlags.NonPublic); foreach (MethodInfo methSearch in methods) { if (methSearch.Name.Equals(this.name, comparison) && methSearch.GetParameters().Length == this.numArgs) throw new XslTransformException(/*[XT_038]*/Res.XmlIl_NonPublicExtensionMethod, this.namespaceUri, this.name); } throw new XslTransformException(/*[XT_039]*/Res.XmlIl_NoExtensionMethod, this.namespaceUri, this.name, this.numArgs.ToString(CultureInfo.InvariantCulture)); } if (methMatch.IsGenericMethodDefinition) throw new XslTransformException(/*[XT_040]*/Res.XmlIl_GenericExtensionMethod, this.namespaceUri, this.name); Debug.Assert(methMatch.ContainsGenericParameters == false); Bind(methMatch); } ////// Bind to the specified MethodInfo. /// private void Bind(MethodInfo meth) { ParameterInfo[] paramInfo = meth.GetParameters(); int i; // Save the MethodInfo this.meth = meth; // Get the Clr type of each parameter this.argClrTypes = new Type[paramInfo.Length]; for (i = 0; i < paramInfo.Length; i++) this.argClrTypes[i] = GetClrType(paramInfo[i].ParameterType); // Get the Clr type of the return value this.retClrType = GetClrType(this.meth.ReturnType); // Infer an Xml type for each Clr type this.argXmlTypes = new XmlQueryType[paramInfo.Length]; for (i = 0; i < paramInfo.Length; i++) { this.argXmlTypes[i] = InferXmlType(this.argClrTypes[i]); // if (this.namespaceUri.Length == 0) { if ((object) this.argXmlTypes[i] == (object) XmlQueryTypeFactory.NodeNotRtf) this.argXmlTypes[i] = XmlQueryTypeFactory.Node; else if ((object) this.argXmlTypes[i] == (object) XmlQueryTypeFactory.NodeSDod) this.argXmlTypes[i] = XmlQueryTypeFactory.NodeS; } else { if ((object) this.argXmlTypes[i] == (object) XmlQueryTypeFactory.NodeSDod) this.argXmlTypes[i] = XmlQueryTypeFactory.NodeNotRtfS; } } // Infer an Xml type for the return Clr type this.retXmlType = InferXmlType(this.retClrType); } ////// Convert the incoming arguments to an array of CLR objects, and then invoke the external function on the "extObj" object instance. /// public object Invoke(object extObj, object[] args) { Debug.Assert(this.meth != null, "Must call Bind() before calling Invoke."); Debug.Assert(args.Length == this.argClrTypes.Length, "Mismatched number of actual and formal arguments."); try { return this.meth.Invoke(extObj, this.flags, null, args, CultureInfo.InvariantCulture); } catch (TargetInvocationException e) { throw new XslTransformException(e.InnerException, Res.XmlIl_ExtensionError, this.name); } catch (Exception e) { if (!XmlException.IsCatchableException(e)) { throw; } throw new XslTransformException(e, Res.XmlIl_ExtensionError, this.name); } } ////// Return true if this XmlExtensionFunction has the same values as another XmlExtensionFunction. /// public override bool Equals(object other) { XmlExtensionFunction that = other as XmlExtensionFunction; Debug.Assert(that != null); // Compare name, argument count, object type, and binding flags return (this.hashCode == that.hashCode && this.name == that.name && this.namespaceUri == that.namespaceUri && this.numArgs == that.numArgs && this.objectType == that.objectType && this.flags == that.flags); } ////// Return this object's hash code, previously computed for performance. /// public override int GetHashCode() { return this.hashCode; } ////// 1. Map enumerations to the underlying integral type. /// 2. Throw an exception if the type is ByRef /// private Type GetClrType(Type clrType) { if (clrType.IsEnum) return Enum.GetUnderlyingType(clrType); if (clrType.IsByRef) throw new XslTransformException(/*[XT_050]*/Res.XmlIl_ByRefType, this.namespaceUri, this.name); return clrType; } ////// Infer an Xml type from a Clr type using Xslt infererence rules /// private XmlQueryType InferXmlType(Type clrType) { return XsltConvert.InferXsltType(clrType); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Xml; using System.Xml.Schema; using System.Reflection; using System.Globalization; using System.Diagnostics; namespace System.Xml.Xsl.Runtime { using Res = System.Xml.Utils.Res; ////// Table of bound extension functions. Once an extension function is bound and entered into the table, future bindings /// will be very fast. This table is not thread-safe. /// internal class XmlExtensionFunctionTable { private Dictionarytable; private XmlExtensionFunction funcCached; public XmlExtensionFunctionTable() { this.table = new Dictionary (); } public XmlExtensionFunction Bind(string name, string namespaceUri, int numArgs, Type objectType, BindingFlags flags) { XmlExtensionFunction func; if (this.funcCached == null) this.funcCached = new XmlExtensionFunction(); // If the extension function already exists in the table, then binding has already been performed this.funcCached.Init(name, namespaceUri, numArgs, objectType, flags); if (!this.table.TryGetValue(this.funcCached, out func)) { // Function doesn't exist, so bind it and enter it into the table func = this.funcCached; this.funcCached = null; func.Bind(); this.table.Add(func, func); } return func; } } /// /// This internal class contains methods that allow binding to extension functions and invoking them. /// internal class XmlExtensionFunction { private string namespaceUri; // Extension object identifier private string name; // Name of this method private int numArgs; // Argument count private Type objectType; // Type of the object which will be searched for matching methods private BindingFlags flags; // Modifiers that were used to search for a matching signature private int hashCode; // Pre-computed hashcode private MethodInfo meth; // MethodInfo for extension function private Type[] argClrTypes; // Type array for extension function arguments private Type retClrType; // Type for extension function return value private XmlQueryType[] argXmlTypes; // XmlQueryType array for extension function arguments private XmlQueryType retXmlType; // XmlQueryType for extension function return value ////// Constructor. /// public XmlExtensionFunction() { } ////// Constructor (directly binds to passed MethodInfo). /// public XmlExtensionFunction(string name, string namespaceUri, MethodInfo meth) { this.name = name; this.namespaceUri = namespaceUri; Bind(meth); } ////// Constructor. /// public XmlExtensionFunction(string name, string namespaceUri, int numArgs, Type objectType, BindingFlags flags) { Init(name, namespaceUri, numArgs, objectType, flags); } ////// Initialize, but do not bind. /// public void Init(string name, string namespaceUri, int numArgs, Type objectType, BindingFlags flags) { this.name = name; this.namespaceUri = namespaceUri; this.numArgs = numArgs; this.objectType = objectType; this.flags = flags; this.meth = null; this.argClrTypes = null; this.retClrType = null; this.argXmlTypes = null; this.retXmlType = null; // Compute hash code so that it is not recomputed each time GetHashCode() is called this.hashCode = namespaceUri.GetHashCode() ^ name.GetHashCode() ^ ((int) flags << 16) ^ (int) numArgs; } ////// Once Bind has been successfully called, Method will be non-null. /// public MethodInfo Method { get { return this.meth; } } ////// Once Bind has been successfully called, the Clr type of each argument can be accessed. /// Note that this may be different than Method.GetParameterInfo().ParameterType. /// public Type GetClrArgumentType(int index) { return this.argClrTypes[index]; } ////// Once Bind has been successfully called, the Clr type of the return value can be accessed. /// Note that this may be different than Method.GetParameterInfo().ReturnType. /// public Type ClrReturnType { get { return this.retClrType; } } ////// Once Bind has been successfully called, the inferred Xml types of the arguments can be accessed. /// public XmlQueryType GetXmlArgumentType(int index) { return this.argXmlTypes[index]; } ////// Once Bind has been successfully called, the inferred Xml type of the return value can be accessed. /// public XmlQueryType XmlReturnType { get { return this.retXmlType; } } ////// Return true if the CLR type specified in the Init() call has a matching method. /// public bool CanBind() { MethodInfo[] methods = this.objectType.GetMethods(this.flags); bool ignoreCase = (this.flags & BindingFlags.IgnoreCase) != 0; StringComparison comparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; // Find method in object type foreach (MethodInfo methSearch in methods) { if (methSearch.Name.Equals(this.name, comparison) && (this.numArgs == -1 || methSearch.GetParameters().Length == this.numArgs)) { // Binding to generic methods will never succeed if (!methSearch.IsGenericMethodDefinition) return true; } } return false; } ////// Bind to the CLR type specified in the Init() call. If a matching method cannot be found, throw an exception. /// public void Bind() { MethodInfo[] methods = this.objectType.GetMethods(this.flags); MethodInfo methMatch = null; bool ignoreCase = (this.flags & BindingFlags.IgnoreCase) != 0; StringComparison comparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; // Find method in object type foreach (MethodInfo methSearch in methods) { if (methSearch.Name.Equals(this.name, comparison) && (this.numArgs == -1 || methSearch.GetParameters().Length == this.numArgs)) { if (methMatch != null) throw new XslTransformException(/*[XT_037]*/Res.XmlIl_AmbiguousExtensionMethod, this.namespaceUri, this.name, this.numArgs.ToString(CultureInfo.InvariantCulture)); methMatch = methSearch; } } if (methMatch == null) { methods = this.objectType.GetMethods(this.flags | BindingFlags.NonPublic); foreach (MethodInfo methSearch in methods) { if (methSearch.Name.Equals(this.name, comparison) && methSearch.GetParameters().Length == this.numArgs) throw new XslTransformException(/*[XT_038]*/Res.XmlIl_NonPublicExtensionMethod, this.namespaceUri, this.name); } throw new XslTransformException(/*[XT_039]*/Res.XmlIl_NoExtensionMethod, this.namespaceUri, this.name, this.numArgs.ToString(CultureInfo.InvariantCulture)); } if (methMatch.IsGenericMethodDefinition) throw new XslTransformException(/*[XT_040]*/Res.XmlIl_GenericExtensionMethod, this.namespaceUri, this.name); Debug.Assert(methMatch.ContainsGenericParameters == false); Bind(methMatch); } ////// Bind to the specified MethodInfo. /// private void Bind(MethodInfo meth) { ParameterInfo[] paramInfo = meth.GetParameters(); int i; // Save the MethodInfo this.meth = meth; // Get the Clr type of each parameter this.argClrTypes = new Type[paramInfo.Length]; for (i = 0; i < paramInfo.Length; i++) this.argClrTypes[i] = GetClrType(paramInfo[i].ParameterType); // Get the Clr type of the return value this.retClrType = GetClrType(this.meth.ReturnType); // Infer an Xml type for each Clr type this.argXmlTypes = new XmlQueryType[paramInfo.Length]; for (i = 0; i < paramInfo.Length; i++) { this.argXmlTypes[i] = InferXmlType(this.argClrTypes[i]); // if (this.namespaceUri.Length == 0) { if ((object) this.argXmlTypes[i] == (object) XmlQueryTypeFactory.NodeNotRtf) this.argXmlTypes[i] = XmlQueryTypeFactory.Node; else if ((object) this.argXmlTypes[i] == (object) XmlQueryTypeFactory.NodeSDod) this.argXmlTypes[i] = XmlQueryTypeFactory.NodeS; } else { if ((object) this.argXmlTypes[i] == (object) XmlQueryTypeFactory.NodeSDod) this.argXmlTypes[i] = XmlQueryTypeFactory.NodeNotRtfS; } } // Infer an Xml type for the return Clr type this.retXmlType = InferXmlType(this.retClrType); } ////// Convert the incoming arguments to an array of CLR objects, and then invoke the external function on the "extObj" object instance. /// public object Invoke(object extObj, object[] args) { Debug.Assert(this.meth != null, "Must call Bind() before calling Invoke."); Debug.Assert(args.Length == this.argClrTypes.Length, "Mismatched number of actual and formal arguments."); try { return this.meth.Invoke(extObj, this.flags, null, args, CultureInfo.InvariantCulture); } catch (TargetInvocationException e) { throw new XslTransformException(e.InnerException, Res.XmlIl_ExtensionError, this.name); } catch (Exception e) { if (!XmlException.IsCatchableException(e)) { throw; } throw new XslTransformException(e, Res.XmlIl_ExtensionError, this.name); } } ////// Return true if this XmlExtensionFunction has the same values as another XmlExtensionFunction. /// public override bool Equals(object other) { XmlExtensionFunction that = other as XmlExtensionFunction; Debug.Assert(that != null); // Compare name, argument count, object type, and binding flags return (this.hashCode == that.hashCode && this.name == that.name && this.namespaceUri == that.namespaceUri && this.numArgs == that.numArgs && this.objectType == that.objectType && this.flags == that.flags); } ////// Return this object's hash code, previously computed for performance. /// public override int GetHashCode() { return this.hashCode; } ////// 1. Map enumerations to the underlying integral type. /// 2. Throw an exception if the type is ByRef /// private Type GetClrType(Type clrType) { if (clrType.IsEnum) return Enum.GetUnderlyingType(clrType); if (clrType.IsByRef) throw new XslTransformException(/*[XT_050]*/Res.XmlIl_ByRefType, this.namespaceUri, this.name); return clrType; } ////// Infer an Xml type from a Clr type using Xslt infererence rules /// private XmlQueryType InferXmlType(Type clrType) { return XsltConvert.InferXsltType(clrType); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- IODescriptionAttribute.cs
- ToolStripGripRenderEventArgs.cs
- TabItemWrapperAutomationPeer.cs
- DnsPermission.cs
- TextDecorationCollection.cs
- SymmetricCryptoHandle.cs
- Function.cs
- Polygon.cs
- RequestNavigateEventArgs.cs
- XmlObjectSerializerReadContext.cs
- MachineKeySection.cs
- QueryOperationResponseOfT.cs
- DetectEofStream.cs
- SerializationInfo.cs
- ItemsControl.cs
- ModuleBuilder.cs
- DataGridView.cs
- GenericPrincipal.cs
- XmlSignificantWhitespace.cs
- DataColumnCollection.cs
- WebPartManager.cs
- StoreItemCollection.cs
- FtpWebResponse.cs
- StrokeFIndices.cs
- HitTestParameters3D.cs
- DefaultValueTypeConverter.cs
- FamilyCollection.cs
- NumericUpDown.cs
- RecordConverter.cs
- SamlAttributeStatement.cs
- BrowserCapabilitiesCodeGenerator.cs
- ConfigurationElementProperty.cs
- SerializationSectionGroup.cs
- Interlocked.cs
- ProcessProtocolHandler.cs
- TransportListener.cs
- ParserContext.cs
- DataGridHyperlinkColumn.cs
- XamlToRtfWriter.cs
- XmlSerializerFaultFormatter.cs
- ToolStripContentPanelRenderEventArgs.cs
- ColumnCollection.cs
- TreeViewHitTestInfo.cs
- EmbeddedMailObjectsCollection.cs
- WebPartEditVerb.cs
- SingleConverter.cs
- ArrayMergeHelper.cs
- Stopwatch.cs
- StreamingContext.cs
- WebPartTracker.cs
- InvalidateEvent.cs
- WebBrowserBase.cs
- XmlSchemaSimpleContentExtension.cs
- CodeSnippetCompileUnit.cs
- HandlerFactoryCache.cs
- ServiceCredentialsElement.cs
- PointUtil.cs
- MessageContractExporter.cs
- MenuCommands.cs
- HMACSHA256.cs
- Pointer.cs
- OutputCacheProfile.cs
- RegexMatchCollection.cs
- SqlDataSource.cs
- DrawingAttributesDefaultValueFactory.cs
- DataGridViewMethods.cs
- FacetDescriptionElement.cs
- FrameDimension.cs
- Semaphore.cs
- CatalogPart.cs
- RangeValueProviderWrapper.cs
- KoreanLunisolarCalendar.cs
- HMACRIPEMD160.cs
- CalendarDesigner.cs
- DataError.cs
- AssociationSetMetadata.cs
- FixedElement.cs
- DrawingDrawingContext.cs
- ReadWriteSpinLock.cs
- CompoundFileDeflateTransform.cs
- sitestring.cs
- ClickablePoint.cs
- OleDbRowUpdatingEvent.cs
- RectAnimation.cs
- XPathParser.cs
- Exception.cs
- ObjectStorage.cs
- X509Certificate.cs
- BooleanToVisibilityConverter.cs
- EventLogEntry.cs
- BaseTemplateParser.cs
- ParallelTimeline.cs
- OutKeywords.cs
- XPathNavigator.cs
- StorageEntityTypeMapping.cs
- AnimatedTypeHelpers.cs
- WindowsClaimSet.cs
- mda.cs
- SqlClientWrapperSmiStream.cs
- CodeGenerator.cs