Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / XmlUtils / System / Xml / Xsl / Runtime / XmlExtensionFunction.cs / 1 / 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 Dictionary table;
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 (Ref.Equals(this.argXmlTypes[i], XmlQueryTypeFactory.NodeNotRtf))
this.argXmlTypes[i] = XmlQueryTypeFactory.Node;
else if (Ref.Equals(this.argXmlTypes[i], XmlQueryTypeFactory.NodeDodS))
this.argXmlTypes[i] = XmlQueryTypeFactory.NodeS;
}
else {
if (Ref.Equals(this.argXmlTypes[i], XmlQueryTypeFactory.NodeDodS))
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 Dictionary table;
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 (Ref.Equals(this.argXmlTypes[i], XmlQueryTypeFactory.NodeNotRtf))
this.argXmlTypes[i] = XmlQueryTypeFactory.Node;
else if (Ref.Equals(this.argXmlTypes[i], XmlQueryTypeFactory.NodeDodS))
this.argXmlTypes[i] = XmlQueryTypeFactory.NodeS;
}
else {
if (Ref.Equals(this.argXmlTypes[i], XmlQueryTypeFactory.NodeDodS))
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
- DBNull.cs
- HttpHandlerAction.cs
- SimpleRecyclingCache.cs
- HGlobalSafeHandle.cs
- HttpFileCollectionWrapper.cs
- SqlBuilder.cs
- TraceLevelHelper.cs
- VisualCollection.cs
- ContainerFilterService.cs
- FormatConvertedBitmap.cs
- ParamArrayAttribute.cs
- OledbConnectionStringbuilder.cs
- SR.cs
- GeneralTransform3DCollection.cs
- SafeRightsManagementPubHandle.cs
- OdbcHandle.cs
- RemotingHelper.cs
- FontStretches.cs
- ResourcePermissionBase.cs
- FileSecurity.cs
- ValidationSummaryDesigner.cs
- AssemblyCache.cs
- versioninfo.cs
- XPathPatternParser.cs
- Label.cs
- EmptyQuery.cs
- DataSourceXmlSerializationAttribute.cs
- HierarchicalDataSourceIDConverter.cs
- SqlDelegatedTransaction.cs
- SQLGuid.cs
- CodePropertyReferenceExpression.cs
- ObjRef.cs
- ServicePoint.cs
- TemplatedAdorner.cs
- ObjectSet.cs
- BevelBitmapEffect.cs
- PrintDialogException.cs
- Schema.cs
- ColumnPropertiesGroup.cs
- UrlAuthorizationModule.cs
- coordinatorscratchpad.cs
- Psha1DerivedKeyGenerator.cs
- OrderedDictionary.cs
- WindowAutomationPeer.cs
- Light.cs
- HashHelper.cs
- FileSystemWatcher.cs
- AdapterDictionary.cs
- WorkflowMessageEventArgs.cs
- PolyQuadraticBezierSegment.cs
- ListBoxItem.cs
- SyndicationFeed.cs
- SafeReversePInvokeHandle.cs
- SvcMapFileSerializer.cs
- ObjectFullSpanRewriter.cs
- DispatcherExceptionFilterEventArgs.cs
- MULTI_QI.cs
- ComPlusServiceLoader.cs
- Canvas.cs
- X509ChainElement.cs
- HandlerFactoryCache.cs
- DisplayNameAttribute.cs
- ConfigurationManagerHelper.cs
- DllNotFoundException.cs
- EventProviderTraceListener.cs
- ExpressionBindings.cs
- MenuAdapter.cs
- Stackframe.cs
- ConstantCheck.cs
- ImageListImage.cs
- ObjectManager.cs
- XslVisitor.cs
- MDIWindowDialog.cs
- filewebresponse.cs
- PermissionRequestEvidence.cs
- GraphicsContext.cs
- FormViewModeEventArgs.cs
- WebPartDesigner.cs
- codemethodreferenceexpression.cs
- FormViewRow.cs
- ToolStripManager.cs
- PerformanceCounterPermissionAttribute.cs
- CompilationLock.cs
- PageContentAsyncResult.cs
- X509CertificateChain.cs
- PrintEvent.cs
- TrimSurroundingWhitespaceAttribute.cs
- ExpressionBuilder.cs
- SortKey.cs
- _Win32.cs
- Canvas.cs
- Composition.cs
- Delegate.cs
- SharedDp.cs
- ObjectQuery.cs
- TextContainerChangedEventArgs.cs
- ApplicationInfo.cs
- SoapHeaderException.cs
- DesignerDataStoredProcedure.cs
- EditorOptionAttribute.cs