Code:
/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / 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;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
- HttpWebRequestElement.cs
- WebPartsSection.cs
- DataGridViewComboBoxColumn.cs
- ClientUriBehavior.cs
- wmiutil.cs
- HostExecutionContextManager.cs
- PositiveTimeSpanValidator.cs
- QilStrConcat.cs
- ConfigUtil.cs
- DataServiceClientException.cs
- SqlUserDefinedAggregateAttribute.cs
- SingleObjectCollection.cs
- ElementsClipboardData.cs
- HttpRequest.cs
- HtmlInputControl.cs
- EventlogProvider.cs
- XmlBoundElement.cs
- HostingPreferredMapPath.cs
- QilReplaceVisitor.cs
- DefaultTextStore.cs
- NeutralResourcesLanguageAttribute.cs
- SQLGuid.cs
- SafeMemoryMappedViewHandle.cs
- TreeNodeBindingDepthConverter.cs
- TCPClient.cs
- TextTreeFixupNode.cs
- InternalResources.cs
- Pen.cs
- GZipDecoder.cs
- UnitySerializationHolder.cs
- RequiredFieldValidator.cs
- PropertyTabAttribute.cs
- DeferredReference.cs
- DodSequenceMerge.cs
- TimersDescriptionAttribute.cs
- ImageCreator.cs
- DataGridViewCellValidatingEventArgs.cs
- FormattedText.cs
- TextBreakpoint.cs
- Predicate.cs
- DescriptionAttribute.cs
- XmlSchemaSimpleContent.cs
- RouteItem.cs
- TimeStampChecker.cs
- TaiwanLunisolarCalendar.cs
- IPeerNeighbor.cs
- ControlEvent.cs
- CharAnimationUsingKeyFrames.cs
- HtmlTitle.cs
- DataGridTextBox.cs
- ObjectDataSourceEventArgs.cs
- ProvidePropertyAttribute.cs
- QueryContinueDragEventArgs.cs
- Symbol.cs
- BrowserCapabilitiesCodeGenerator.cs
- TextRangeBase.cs
- VerificationException.cs
- ListViewUpdateEventArgs.cs
- ImageDrawing.cs
- KeyValuePair.cs
- EdmComplexPropertyAttribute.cs
- TableLayoutSettingsTypeConverter.cs
- UInt32Storage.cs
- EdmMember.cs
- Logging.cs
- UserMapPath.cs
- DependencyPropertyConverter.cs
- CorrelationTokenTypeConvertor.cs
- Publisher.cs
- LineVisual.cs
- DesignerDeviceConfig.cs
- ColumnWidthChangingEvent.cs
- CheckBoxBaseAdapter.cs
- arclist.cs
- ComplexTypeEmitter.cs
- FunctionNode.cs
- ReadOnlyHierarchicalDataSource.cs
- UnsafeNativeMethods.cs
- SiteIdentityPermission.cs
- AtomMaterializerLog.cs
- UrlMappingCollection.cs
- ContentWrapperAttribute.cs
- HelpKeywordAttribute.cs
- IdentifierService.cs
- X509Utils.cs
- MimePart.cs
- RecordManager.cs
- Bidi.cs
- PasswordDeriveBytes.cs
- LogWriteRestartAreaAsyncResult.cs
- ArrangedElement.cs
- StringAttributeCollection.cs
- counter.cs
- WebRequestModuleElement.cs
- RenderCapability.cs
- PieceDirectory.cs
- XmlSchemaType.cs
- serverconfig.cs
- Util.cs
- SafeIUnknown.cs