Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / clr / src / BCL / System / DefaultBinder.cs / 1 / DefaultBinder.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // // This class represents the Default COM+ binder. // // namespace System { using System; using System.Reflection; using System.Runtime.CompilerServices; using CultureInfo = System.Globalization.CultureInfo; //Marked serializable even though it has no state. [Serializable()] internal class DefaultBinder : Binder { // This method is passed a set of methods and must choose the best // fit. The methods all have the same number of arguments and the object // array args. On exit, this method will choice the best fit method // and coerce the args to match that method. By match, we mean all primitive // arguments are exact matchs and all object arguments are exact or subclasses // of the target. If the target OR is an interface, the object must implement // that interface. There are a couple of exceptions // thrown when a method cannot be returned. If no method matchs the args and // ArgumentException is thrown. If multiple methods match the args then // an AmbiguousMatchException is thrown. // // The most specific match will be selected. // public override MethodBase BindToMethod( BindingFlags bindingAttr, MethodBase[] canidates, ref Object[] args, ParameterModifier[] modifiers, CultureInfo cultureInfo, String[] names, out Object state) { int i; int j; state = null; if (canidates == null || canidates.Length == 0) throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"),"canidates"); #region Map named parameters to canidate parameter postions // We are creating an paramOrder array to act as a mapping // between the order of the args and the actual order of the // parameters in the method. This order may differ because // named parameters (names) may change the order. If names // is not provided, then we assume the default mapping (0,1,...) int[][] paramOrder = new int[canidates.Length][]; for (i = 0; i < canidates.Length; i++) { ParameterInfo[] par = canidates[i].GetParametersNoCopy(); // args.Length + 1 takes into account the possibility of a last paramArray that can be omitted paramOrder[i] = new int[(par.Length > args.Length) ? par.Length : args.Length]; if (names == null) { // Default mapping for (j = 0; j < args.Length; j++) paramOrder[i][j] = j; } else { // Named parameters, reorder the mapping. If CreateParamOrder fails, it means that the method // doesn't have a name that matchs one of the named parameters so we don't consider it any further. if (!CreateParamOrder(paramOrder[i], par, names)) canidates[i] = null; } } #endregion Type[] paramArrayTypes = new Type[canidates.Length]; Type[] argTypes = new Type[args.Length]; #region Cache the type of the provided arguments // object that contain a null are treated as if they were typeless (but match either object // references or value classes). We mark this condition by placing a null in the argTypes array. for (i = 0; i < args.Length; i++) { if (args[i] != null) { argTypes[i] = args[i].GetType(); } } #endregion // Find the method that matches... int CurIdx = 0; bool defaultValueBinding = ((bindingAttr & BindingFlags.OptionalParamBinding) != 0); Type paramArrayType = null; #region Filter methods by parameter count and type for (i = 0; i < canidates.Length; i++) { paramArrayType = null; // If we have named parameters then we may have a hole in the canidates array. if (canidates[i] == null) continue; // Validate the parameters. ParameterInfo[] par = canidates[i].GetParametersNoCopy(); #region Match method by parameter count if (par.Length == 0) { #region No formal parameters if (args.Length != 0) { if ((canidates[i].CallingConvention & CallingConventions.VarArgs) == 0) continue; } // This is a valid routine so we move it up the canidates list. paramOrder[CurIdx] = paramOrder[i]; canidates[CurIdx++] = canidates[i]; continue; #endregion } else if (par.Length > args.Length) { #region Shortage of provided parameters // If the number of parameters is greater than the number of args then // we are in the situation were we may be using default values. for (j = args.Length; j < par.Length - 1; j++) { if (par[j].DefaultValue == System.DBNull.Value) break; } if (j != par.Length - 1) continue; if (par[j].DefaultValue == System.DBNull.Value) { if (!par[j].ParameterType.IsArray) continue; if (!par[j].IsDefined(typeof(ParamArrayAttribute), true)) continue; paramArrayType = par[j].ParameterType.GetElementType(); } #endregion } else if (par.Length < args.Length) { #region Excess provided parameters // test for the ParamArray case int lastArgPos = par.Length - 1; if (!par[lastArgPos].ParameterType.IsArray) continue; if (!par[lastArgPos].IsDefined(typeof(ParamArrayAttribute), true)) continue; if (paramOrder[i][lastArgPos] != lastArgPos) continue; paramArrayType = par[lastArgPos].ParameterType.GetElementType(); #endregion } else { #region Test for paramArray, save paramArray type int lastArgPos = par.Length - 1; if (par[lastArgPos].ParameterType.IsArray && par[lastArgPos].IsDefined(typeof(ParamArrayAttribute), true) && paramOrder[i][lastArgPos] == lastArgPos) { if (!par[lastArgPos].ParameterType.IsAssignableFrom(argTypes[lastArgPos])) paramArrayType = par[lastArgPos].ParameterType.GetElementType(); } #endregion } #endregion Type pCls = null; int argsToCheck = (paramArrayType != null) ? par.Length - 1 : args.Length; #region Match method by parameter type for (j = 0; j < argsToCheck; j++) { #region Classic argument coersion checks // get the formal type pCls = par[j].ParameterType; if (pCls.IsByRef) pCls = pCls.GetElementType(); // the type is the same if (pCls == argTypes[paramOrder[i][j]]) continue; // a default value is available if (defaultValueBinding && args[paramOrder[i][j]] == Type.Missing) continue; // the argument was null, so it matches with everything if (args[paramOrder[i][j]] == null) continue; // the type is Object, so it will match everything if (pCls == typeof(Object)) continue; // now do a "classic" type check if (pCls.IsPrimitive) { if (argTypes[paramOrder[i][j]] == null || !CanConvertPrimitiveObjectToType(args[paramOrder[i][j]],(RuntimeType)pCls)) { #if !FEATURE_COMINTEROP if (CanChangeType(args[paramOrder[i][j]],pCls,cultureInfo)) continue; #endif break; } } else { if (argTypes[paramOrder[i][j]] == null) continue; if (!pCls.IsAssignableFrom(argTypes[paramOrder[i][j]])) { if (argTypes[paramOrder[i][j]].IsCOMObject) { if (pCls.IsInstanceOfType(args[paramOrder[i][j]])) continue; } #if !FEATURE_COMINTEROP if (CanChangeType(args[paramOrder[i][j]],pCls,cultureInfo)) continue; #endif break; } } #endregion } if (paramArrayType != null && j == par.Length - 1) { #region Check that excess arguments can be placed in the param array for (; j < args.Length; j++) { if (paramArrayType.IsPrimitive) { if (argTypes[j] == null || !CanConvertPrimitiveObjectToType(args[j], (RuntimeType)paramArrayType)) break; } else { if (argTypes[j] == null) continue; if (!paramArrayType.IsAssignableFrom(argTypes[j])) { if (argTypes[j].IsCOMObject) { if (paramArrayType.IsInstanceOfType(args[j])) continue; } break; } } } #endregion } #endregion if (j == args.Length) { #region This is a valid routine so we move it up the canidates list paramOrder[CurIdx] = paramOrder[i]; paramArrayTypes[CurIdx] = paramArrayType; canidates[CurIdx++] = canidates[i]; #endregion } } #endregion // If we didn't find a method if (CurIdx == 0) throw new MissingMethodException(Environment.GetResourceString("MissingMember")); if (CurIdx == 1) { #region Found only one method if (names != null) { state = new BinderState((int[])paramOrder[0].Clone(), args.Length, paramArrayTypes[0] != null); ReorderParams(paramOrder[0],args); } // If the parameters and the args are not the same length or there is a paramArray // then we need to create a argument array. ParameterInfo[] parms = canidates[0].GetParametersNoCopy(); if (parms.Length == args.Length) { if (paramArrayTypes[0] != null) { Object[] objs = new Object[parms.Length]; int lastPos = parms.Length - 1; Array.Copy(args, 0, objs, 0, lastPos); objs[lastPos] = Array.CreateInstance(paramArrayTypes[0], 1); ((Array)objs[lastPos]).SetValue(args[lastPos], 0); args = objs; } } else if (parms.Length > args.Length) { Object[] objs = new Object[parms.Length]; for (i=0;iargs.Length) { Object[] objs = new Object[parameters.Length]; for (i=0;i binderState.m_originalSize) { Object[] newArgs = new Object[binderState.m_originalSize]; Array.Copy(args, 0, newArgs, 0, binderState.m_originalSize); args = newArgs; } } } // Return any exact bindings that may exist. (This method is not defined on the // Binder and is used by RuntimeType.) public static MethodBase ExactBinding(MethodBase[] match,Type[] types,ParameterModifier[] modifiers) { if (match==null) throw new ArgumentNullException("match"); MethodBase[] aExactMatches = new MethodBase[match.Length]; int cExactMatches = 0; for (int i=0;i deepestHierarchy) { deepestHierarchy = currentHierarchyDepth; methWithDeepestHierarchy = match[i]; } } return methWithDeepestHierarchy; } // CanConvertPrimitive // This will determine if the source can be converted to the target type [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool CanConvertPrimitive(RuntimeType source,RuntimeType target); // CanConvertPrimitiveObjectToType // This method will determine if the primitive object can be converted // to a type. [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern bool CanConvertPrimitiveObjectToType(Object source,RuntimeType type); // This method will sort the vars array into the mapping order stored // in the paramOrder array. private static void ReorderParams(int[] paramOrder,Object[] vars) { // This is an O(n) algorithm for sorting the array. // For each position in the paramOrder array we swap the value // stored there into it's position until we swap position i into i. // This moves things exactly the number of items out of position. for (int i=0;i args.Length) ? par.Length : args.Length]; if (names == null) { // Default mapping for (j = 0; j < args.Length; j++) paramOrder[i][j] = j; } else { // Named parameters, reorder the mapping. If CreateParamOrder fails, it means that the method // doesn't have a name that matchs one of the named parameters so we don't consider it any further. if (!CreateParamOrder(paramOrder[i], par, names)) canidates[i] = null; } } #endregion Type[] paramArrayTypes = new Type[canidates.Length]; Type[] argTypes = new Type[args.Length]; #region Cache the type of the provided arguments // object that contain a null are treated as if they were typeless (but match either object // references or value classes). We mark this condition by placing a null in the argTypes array. for (i = 0; i < args.Length; i++) { if (args[i] != null) { argTypes[i] = args[i].GetType(); } } #endregion // Find the method that matches... int CurIdx = 0; bool defaultValueBinding = ((bindingAttr & BindingFlags.OptionalParamBinding) != 0); Type paramArrayType = null; #region Filter methods by parameter count and type for (i = 0; i < canidates.Length; i++) { paramArrayType = null; // If we have named parameters then we may have a hole in the canidates array. if (canidates[i] == null) continue; // Validate the parameters. ParameterInfo[] par = canidates[i].GetParametersNoCopy(); #region Match method by parameter count if (par.Length == 0) { #region No formal parameters if (args.Length != 0) { if ((canidates[i].CallingConvention & CallingConventions.VarArgs) == 0) continue; } // This is a valid routine so we move it up the canidates list. paramOrder[CurIdx] = paramOrder[i]; canidates[CurIdx++] = canidates[i]; continue; #endregion } else if (par.Length > args.Length) { #region Shortage of provided parameters // If the number of parameters is greater than the number of args then // we are in the situation were we may be using default values. for (j = args.Length; j < par.Length - 1; j++) { if (par[j].DefaultValue == System.DBNull.Value) break; } if (j != par.Length - 1) continue; if (par[j].DefaultValue == System.DBNull.Value) { if (!par[j].ParameterType.IsArray) continue; if (!par[j].IsDefined(typeof(ParamArrayAttribute), true)) continue; paramArrayType = par[j].ParameterType.GetElementType(); } #endregion } else if (par.Length < args.Length) { #region Excess provided parameters // test for the ParamArray case int lastArgPos = par.Length - 1; if (!par[lastArgPos].ParameterType.IsArray) continue; if (!par[lastArgPos].IsDefined(typeof(ParamArrayAttribute), true)) continue; if (paramOrder[i][lastArgPos] != lastArgPos) continue; paramArrayType = par[lastArgPos].ParameterType.GetElementType(); #endregion } else { #region Test for paramArray, save paramArray type int lastArgPos = par.Length - 1; if (par[lastArgPos].ParameterType.IsArray && par[lastArgPos].IsDefined(typeof(ParamArrayAttribute), true) && paramOrder[i][lastArgPos] == lastArgPos) { if (!par[lastArgPos].ParameterType.IsAssignableFrom(argTypes[lastArgPos])) paramArrayType = par[lastArgPos].ParameterType.GetElementType(); } #endregion } #endregion Type pCls = null; int argsToCheck = (paramArrayType != null) ? par.Length - 1 : args.Length; #region Match method by parameter type for (j = 0; j < argsToCheck; j++) { #region Classic argument coersion checks // get the formal type pCls = par[j].ParameterType; if (pCls.IsByRef) pCls = pCls.GetElementType(); // the type is the same if (pCls == argTypes[paramOrder[i][j]]) continue; // a default value is available if (defaultValueBinding && args[paramOrder[i][j]] == Type.Missing) continue; // the argument was null, so it matches with everything if (args[paramOrder[i][j]] == null) continue; // the type is Object, so it will match everything if (pCls == typeof(Object)) continue; // now do a "classic" type check if (pCls.IsPrimitive) { if (argTypes[paramOrder[i][j]] == null || !CanConvertPrimitiveObjectToType(args[paramOrder[i][j]],(RuntimeType)pCls)) { #if !FEATURE_COMINTEROP if (CanChangeType(args[paramOrder[i][j]],pCls,cultureInfo)) continue; #endif break; } } else { if (argTypes[paramOrder[i][j]] == null) continue; if (!pCls.IsAssignableFrom(argTypes[paramOrder[i][j]])) { if (argTypes[paramOrder[i][j]].IsCOMObject) { if (pCls.IsInstanceOfType(args[paramOrder[i][j]])) continue; } #if !FEATURE_COMINTEROP if (CanChangeType(args[paramOrder[i][j]],pCls,cultureInfo)) continue; #endif break; } } #endregion } if (paramArrayType != null && j == par.Length - 1) { #region Check that excess arguments can be placed in the param array for (; j < args.Length; j++) { if (paramArrayType.IsPrimitive) { if (argTypes[j] == null || !CanConvertPrimitiveObjectToType(args[j], (RuntimeType)paramArrayType)) break; } else { if (argTypes[j] == null) continue; if (!paramArrayType.IsAssignableFrom(argTypes[j])) { if (argTypes[j].IsCOMObject) { if (paramArrayType.IsInstanceOfType(args[j])) continue; } break; } } } #endregion } #endregion if (j == args.Length) { #region This is a valid routine so we move it up the canidates list paramOrder[CurIdx] = paramOrder[i]; paramArrayTypes[CurIdx] = paramArrayType; canidates[CurIdx++] = canidates[i]; #endregion } } #endregion // If we didn't find a method if (CurIdx == 0) throw new MissingMethodException(Environment.GetResourceString("MissingMember")); if (CurIdx == 1) { #region Found only one method if (names != null) { state = new BinderState((int[])paramOrder[0].Clone(), args.Length, paramArrayTypes[0] != null); ReorderParams(paramOrder[0],args); } // If the parameters and the args are not the same length or there is a paramArray // then we need to create a argument array. ParameterInfo[] parms = canidates[0].GetParametersNoCopy(); if (parms.Length == args.Length) { if (paramArrayTypes[0] != null) { Object[] objs = new Object[parms.Length]; int lastPos = parms.Length - 1; Array.Copy(args, 0, objs, 0, lastPos); objs[lastPos] = Array.CreateInstance(paramArrayTypes[0], 1); ((Array)objs[lastPos]).SetValue(args[lastPos], 0); args = objs; } } else if (parms.Length > args.Length) { Object[] objs = new Object[parms.Length]; for (i=0;i args.Length) { Object[] objs = new Object[parameters.Length]; for (i=0;i binderState.m_originalSize) { Object[] newArgs = new Object[binderState.m_originalSize]; Array.Copy(args, 0, newArgs, 0, binderState.m_originalSize); args = newArgs; } } } // Return any exact bindings that may exist. (This method is not defined on the // Binder and is used by RuntimeType.) public static MethodBase ExactBinding(MethodBase[] match,Type[] types,ParameterModifier[] modifiers) { if (match==null) throw new ArgumentNullException("match"); MethodBase[] aExactMatches = new MethodBase[match.Length]; int cExactMatches = 0; for (int i=0;i deepestHierarchy) { deepestHierarchy = currentHierarchyDepth; methWithDeepestHierarchy = match[i]; } } return methWithDeepestHierarchy; } // CanConvertPrimitive // This will determine if the source can be converted to the target type [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool CanConvertPrimitive(RuntimeType source,RuntimeType target); // CanConvertPrimitiveObjectToType // This method will determine if the primitive object can be converted // to a type. [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern bool CanConvertPrimitiveObjectToType(Object source,RuntimeType type); // This method will sort the vars array into the mapping order stored // in the paramOrder array. private static void ReorderParams(int[] paramOrder,Object[] vars) { // This is an O(n) algorithm for sorting the array. // For each position in the paramOrder array we swap the value // stored there into it's position until we swap position i into i. // This moves things exactly the number of items out of position. for (int i=0;i
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- UnsafeNativeMethods.cs
- SmiEventStream.cs
- PathNode.cs
- ContentDisposition.cs
- SpeakCompletedEventArgs.cs
- XmlQuerySequence.cs
- XamlSerializationHelper.cs
- DataGridViewColumnCollection.cs
- PropertyChangeTracker.cs
- SerTrace.cs
- RangeBaseAutomationPeer.cs
- While.cs
- FrugalMap.cs
- PageThemeBuildProvider.cs
- XmlArrayItemAttribute.cs
- ConfigXmlDocument.cs
- SecurityUtils.cs
- TextRange.cs
- DetailsViewInsertEventArgs.cs
- PreservationFileWriter.cs
- RootDesignerSerializerAttribute.cs
- TcpSocketManager.cs
- MethodBuilder.cs
- DrawingState.cs
- XmlElementAttributes.cs
- WMICapabilities.cs
- QilTypeChecker.cs
- Vector3D.cs
- assemblycache.cs
- AnimationTimeline.cs
- _LocalDataStore.cs
- StringBlob.cs
- _AutoWebProxyScriptEngine.cs
- RegexParser.cs
- QilTargetType.cs
- StringFreezingAttribute.cs
- DateTimeConverter2.cs
- GenericEnumConverter.cs
- Privilege.cs
- MutexSecurity.cs
- SerializationException.cs
- SQLDateTimeStorage.cs
- ItemList.cs
- Timer.cs
- ContextMenuService.cs
- NameValuePair.cs
- NavigationPropertyEmitter.cs
- peernodeimplementation.cs
- AdapterDictionary.cs
- WebPartCloseVerb.cs
- DockPanel.cs
- LogicalTreeHelper.cs
- QueryOutputWriter.cs
- LicFileLicenseProvider.cs
- WsatServiceAddress.cs
- OlePropertyStructs.cs
- DynamicILGenerator.cs
- PagesSection.cs
- DuplicateWaitObjectException.cs
- TextAdaptor.cs
- RawContentTypeMapper.cs
- HttpModuleActionCollection.cs
- AssemblyContextControlItem.cs
- TreeWalker.cs
- KoreanCalendar.cs
- ClientRuntimeConfig.cs
- ContentHostHelper.cs
- _SslStream.cs
- ToolStripPanelRenderEventArgs.cs
- DataControlFieldHeaderCell.cs
- COM2PropertyDescriptor.cs
- DBDataPermission.cs
- HttpValueCollection.cs
- EnlistmentTraceIdentifier.cs
- smtppermission.cs
- HeaderedItemsControl.cs
- ResourceReferenceExpression.cs
- GeneralTransform3DTo2D.cs
- EpmTargetPathSegment.cs
- QueryModel.cs
- IdentityReference.cs
- InternalResources.cs
- XamlPointCollectionSerializer.cs
- SoundPlayer.cs
- SortQuery.cs
- UnsafeNativeMethodsMilCoreApi.cs
- ElementProxy.cs
- Int32RectValueSerializer.cs
- Comparer.cs
- StateWorkerRequest.cs
- ConstraintStruct.cs
- CheckBox.cs
- MexBindingBindingCollectionElement.cs
- PrivilegeNotHeldException.cs
- BinaryObjectInfo.cs
- KeyValueInternalCollection.cs
- ToolTipAutomationPeer.cs
- CloudCollection.cs
- SiteMapHierarchicalDataSourceView.cs
- WindowsToolbarAsMenu.cs