Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- InputReferenceExpression.cs
- DataGridHeaderBorder.cs
- WasHttpHandlersInstallComponent.cs
- QilParameter.cs
- Formatter.cs
- wgx_sdk_version.cs
- ActivityLocationReferenceEnvironment.cs
- ColorInterpolationModeValidation.cs
- RequestResizeEvent.cs
- StorageMappingItemCollection.cs
- CalendarDataBindingHandler.cs
- DBNull.cs
- Track.cs
- XmlWrappingReader.cs
- BitmapEffectGroup.cs
- SessionEndedEventArgs.cs
- CollectionCodeDomSerializer.cs
- GridViewRow.cs
- RoleService.cs
- GlyphInfoList.cs
- HtmlWindow.cs
- Single.cs
- DataGridViewCellStyleConverter.cs
- StreamUpgradeAcceptor.cs
- MasterPageParser.cs
- XmlJsonReader.cs
- ManifestResourceInfo.cs
- KerberosSecurityTokenParameters.cs
- PerformanceCounterPermissionAttribute.cs
- brushes.cs
- DispatchChannelSink.cs
- WindowsListViewItemStartMenu.cs
- CompilationSection.cs
- DBCommandBuilder.cs
- ZipIOCentralDirectoryFileHeader.cs
- TemplateControl.cs
- ElementHostPropertyMap.cs
- PlainXmlSerializer.cs
- StreamResourceInfo.cs
- MemberInfoSerializationHolder.cs
- HttpTransportSecurity.cs
- XappLauncher.cs
- OperationCanceledException.cs
- WindowsRebar.cs
- AuthenticationException.cs
- ResourceManager.cs
- Rect3D.cs
- RequiredFieldValidator.cs
- XamlSerializer.cs
- ServiceAuthorizationElement.cs
- PropertyBuilder.cs
- GenericXmlSecurityToken.cs
- Binding.cs
- DataGridCellEditEndingEventArgs.cs
- OrderByBuilder.cs
- MessagingDescriptionAttribute.cs
- BitmapEffectrendercontext.cs
- SecurityCookieModeValidator.cs
- IntSecurity.cs
- BrushMappingModeValidation.cs
- HtmlTable.cs
- TiffBitmapEncoder.cs
- EndPoint.cs
- StrokeFIndices.cs
- HandleRef.cs
- HttpListenerContext.cs
- CachedPathData.cs
- CatalogZone.cs
- MultiSelectRootGridEntry.cs
- SmtpException.cs
- Image.cs
- AuthenticationService.cs
- RuntimeHandles.cs
- KeyBinding.cs
- RoleServiceManager.cs
- LinqDataSourceUpdateEventArgs.cs
- LayoutEditorPart.cs
- InternalRelationshipCollection.cs
- ServiceNotStartedException.cs
- Boolean.cs
- recordstate.cs
- PageSetupDialog.cs
- OrderingExpression.cs
- CodeCatchClauseCollection.cs
- EventMappingSettings.cs
- FileInfo.cs
- WebResponse.cs
- PageContentAsyncResult.cs
- MachinePropertyVariants.cs
- CompilerLocalReference.cs
- Catch.cs
- ByteStream.cs
- OleDbDataAdapter.cs
- Visual3D.cs
- SizeChangedEventArgs.cs
- UnknownWrapper.cs
- ConfigurationValidatorAttribute.cs
- WebPartTransformerCollection.cs
- _CacheStreams.cs
- DataGridTextColumn.cs