5 // Marco Ridoni (marco.ridoni@virgilio.it)
6 // Satya Sudha K (ksathyasudha@novell.com)
8 // (C) 2003 Marco Ridoni
12 // Copyright (c) 2002-2003 Mainsoft Corporation.
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Collections;
36 using System.Reflection;
37 using System.Globalization;
38 using Microsoft.VisualBasic;
39 using System.ComponentModel;
42 namespace Microsoft.VisualBasic.CompilerServices
44 [StandardModule, EditorBrowsableAttribute(EditorBrowsableState.Never)]
45 public class VBBinder : Binder
47 public VBBinder() : base()
51 public VBBinder(bool [] CopyBack) : base()
53 byRefFlags = CopyBack;
56 private class BinderState
58 public object[] originalArgs;
59 public bool[] byRefFlags;
63 public enum ConversionType {
70 public override FieldInfo BindToField(
71 BindingFlags bindingAttr,
80 private bool[] byRefFlags;
81 private Type objectType;
82 private string bindToName;
84 // This method selects a suitable method for the given arguments
85 // Step 1 : Filter out all the methods that are not applicable
86 // Step 2 : Out of the remaining methods, retain only the methods of the most derived types
87 // Step 3 : Get the kind of conversions (Widening, Exact, Narrowing) to be made to the
88 // arguments to make them applicable. Remember the best match found so far.
89 // If two or more candidates require narrowing conversions - Report error
90 // If two candidates X and Y require widening conversions, then
91 // * select X if conversions from parameters of X to correspodning parameters
92 // of Y are all widening.
93 // * select Y if conversions from parameters of Y to correspodning parameters
94 // of X are all widening.
95 // * otherwise ambiguous
96 // Step 4: Once a best match of found, contruct a new argument list for that method using
97 // the given parameters :
98 // * If ParamArray parameters are present then put all the corresponding arguments
100 // For example, while invoking a method
101 // 'F (a As Integer, b as Integer, ParamArray c() As Integer)'
104 // the new argument list should look like (1,2 {3,4,5,6})
105 // - Note : Named arguments dont come into picture here as they are not supported
106 // with ParamArray parameters
107 // * Create an argument order;
108 // * If an argument is Missing or the corresponding argOrder entry is -1,
109 // create an argument with the parameter's default value.
110 // * Perform appropriate conversions.
111 // * set the 'ByRefFlags array properly ('ByRefFlags' is an array to indicate,
112 // which arguments matched a 'ByRef' parameter)
113 public override MethodBase BindToMethod(
114 BindingFlags bindingAttr,
117 ParameterModifier[] modifiers,
122 // Store the original arguments to the method in a state object.
123 BinderState binderState = new BinderState();
124 binderState.originalArgs = args;
125 binderState.byRefFlags = this.byRefFlags;
128 MethodBase mbase = null;
130 if(match == null || match.Length == 0)
131 throw new ArgumentNullException();
133 ArrayList candidates = new ArrayList ();
134 // Get the list of all suitable methods
137 for (int index = 0; index < match.Length; index ++) {
138 if (IsApplicable (match [index], names, args, ref errMsg))
139 candidates.Add (match [index]);
142 if (candidates.Count == 0) {
143 if (match.Length == 1 && errMsg != "")
144 throw new ArgumentException (errMsg);
149 MemberInfo[] tempMatchList = GetMostDerivedMembers (candidates);
150 MethodBase[] filteredMatchList = new MethodBase [tempMatchList.Length];
151 for (int index = 0; index < tempMatchList.Length; index ++)
152 filteredMatchList [index] = (MethodBase) tempMatchList [index];
154 ConversionType bestMatch = ConversionType.None;
155 int numWideningConversions = 0, numNarrowingConversions = 0;
156 ArrayList narrowingConv = new ArrayList ();
157 ArrayList wideningConv = new ArrayList ();
159 for(int x = 0; x < filteredMatchList.Length; x++)
161 ParameterInfo[] parameters = filteredMatchList [x].GetParameters();
162 ConversionType ctype = GetConversionType (parameters, args, names);
163 if (ctype == ConversionType.None)
165 if (ctype == ConversionType.Widening)
166 wideningConv.Add (filteredMatchList[x]);
167 if (ctype == ConversionType.Narrowing)
168 narrowingConv.Add (filteredMatchList[x]);
169 if (bestMatch == ConversionType.None || ctype < bestMatch) {
171 if (ctype == ConversionType.Narrowing)
172 numNarrowingConversions ++;
173 if (ctype == ConversionType.Widening)
174 numWideningConversions ++;
175 mbase = filteredMatchList [x];
176 } else if (bestMatch == ctype) {
177 if (bestMatch == ConversionType.Widening || bestMatch == ConversionType.Exact) {
178 // Got a widening conversion before also.
179 // Find the best among the two
180 int closestMatch = GetClosestMatch (mbase, filteredMatchList [x], args.Length);
181 if (closestMatch == -1) { // Ambiguous
182 numWideningConversions ++;
185 numWideningConversions = 0;
186 if (closestMatch == 1)
187 mbase = filteredMatchList [x];
189 numNarrowingConversions ++;
194 if (bestMatch == ConversionType.Narrowing && numNarrowingConversions > 1) {
195 //TODO : print the methods too
196 throw new AmbiguousMatchException ("No overloaded '" + this.objectType + "." + this.bindToName + "' can be called without a narrowing conversion");
199 if ((bestMatch == ConversionType.Widening || bestMatch == ConversionType.Exact) && numWideningConversions > 1) {
200 //TODO : print the methods too
201 throw new AmbiguousMatchException ("No overloaded '" + this.objectType + "." + this.bindToName + "' can be called without a widening conversion");
207 ParameterInfo[] pars = mbase.GetParameters ();
208 if (pars.Length == 0)
211 int [] argOrder = null;
212 if (!CreateArgOrder (pars, names, args.Length, out argOrder))
216 if (UsesParamArray (pars)) {
218 int paramArrayIndex = pars.GetUpperBound (0);
219 Type paramArrayType = pars [paramArrayIndex].ParameterType;
220 Array paramArgs = Array.CreateInstance (paramArrayType.GetElementType (), args.Length - paramArrayIndex);
221 bool isArgArray = false;
222 if (pars.GetUpperBound (0) + 1 == args.Length) {
223 if (args [pars.GetUpperBound (0)].GetType().IsArray)
228 for (int y = paramArrayIndex; y < args.Length; y ++) {
229 Type dest_type = paramArrayType;
230 if (!args [y].GetType ().IsArray) {
231 dest_type = paramArrayType.GetElementType ();
233 if((args [y] = ObjectType.CTypeHelper (args[y], dest_type)) != null) {
234 paramArgs.SetValue (args [y], index);
240 object[] newArgs = new object [pars.Length];
241 Array.Copy (args, newArgs, paramArrayIndex);
242 newArgs [newArgs.GetUpperBound (0)] = paramArgs;
247 object[] newArguments = new object [pars.Length];
248 args.CopyTo (newArguments, 0);
249 if (!CreateArgOrder (pars, names, args.Length, out argOrder))
251 int numExpectedArgs = pars.Length;
252 if (UsesParamArray (pars))
257 for(int y = 0; y < numExpectedArgs; y++)
260 if (argIndex < argOrder.Length)
261 argIndex = argOrder [y];
262 if (argIndex == -1 || argIndex >= args.Length) // Missing arguments (trailing)
263 newArguments [y] = pars [y].DefaultValue;
264 else if (argIndex < args.Length) {
265 if (args [argIndex] is Missing)
266 newArguments [y] = pars [y].DefaultValue;
268 newArguments [y] = args [argIndex];
272 for(int y = 0; y < numExpectedArgs; y++) {
273 if (newArguments [y] == null)
276 if((newArguments [y] = ObjectType.CTypeHelper (newArguments[y], pars[y].ParameterType)) == null)
284 private int GetClosestMatch (MethodBase bestMatch, MethodBase candidate, int argCount) {
285 // flag to indicate which one has been better so far
286 // -1 : none is better than other
287 // 0 : bestMatch has been better so far
288 // 1 : candidate is better than bestMatch
290 ParameterInfo[] bestMatchParams = bestMatch.GetParameters ();
291 ParameterInfo[] candidateParams = candidate.GetParameters ();
292 int paramArrayIndex1 = -1, paramArrayIndex2 = -1;
293 if (UsesParamArray (bestMatchParams)) {
294 paramArrayIndex1 = (bestMatchParams.Length > 0) ? (bestMatchParams.Length - 1) : -1;
297 if (UsesParamArray (candidateParams)) {
298 paramArrayIndex2 = (candidateParams.Length > 0) ? (candidateParams.Length - 1) : -1;
301 for (int i = 0; i < argCount; i ++) {
302 int index1 = i, index2 = i;
303 Type bestMatchParamsType = null;
304 Type candParamType = null;
305 if (i >= paramArrayIndex1 && paramArrayIndex1 != -1) {
306 index1 = paramArrayIndex1;
307 bestMatchParamsType = bestMatchParams [index1].ParameterType.GetElementType ();
309 bestMatchParamsType = bestMatchParams [index1].ParameterType;
310 if (i >= paramArrayIndex2 && paramArrayIndex2 != -1) {
311 index2 = paramArrayIndex2;
312 candParamType = candidateParams [index2].ParameterType.GetElementType ();
314 candParamType = candidateParams [index2].ParameterType;
317 if (bestMatchParamsType == candParamType)
320 if (ObjectType.IsWideningConversion (bestMatchParamsType, candParamType)) {
321 // ith param of candidate is wider than that of bestMatch
322 if (isBetter == -2) {
325 } else if (isBetter != 0) {
331 } else if (ObjectType.IsWideningConversion (candParamType, bestMatchParamsType)) {
332 // ith param of bestMatch is wider than that of candidate
333 if (isBetter == -2) {
336 } else if (isBetter != 1) {
344 if (isBetter == -2) {
345 // corresponding parameters of both methods have same types
346 // the method having max no of fixed parameters is better
347 if (paramArrayIndex1 == -1 && paramArrayIndex2 != -1)
349 if (paramArrayIndex1 != -1 && paramArrayIndex2 == -1)
351 return ((paramArrayIndex1 < paramArrayIndex2) ? 1 : 0);
357 // Determines is there is any 'ParamArray' parameter in the given set of param
358 internal static bool UsesParamArray (ParameterInfo [] pars) {
359 if (pars == null || pars.Length == 0)
361 ParameterInfo lastParam = pars [pars.GetUpperBound (0)];
362 object[] attrs = lastParam.GetCustomAttributes (typeof (System.ParamArrayAttribute), false);
363 if (attrs == null || attrs.Length == 0)
368 // Gets the number of parameters that are neither optional not ParamArray
369 internal static int CountStandardParams (ParameterInfo [] pars) {
370 if (pars.Length == 0)
372 int count = pars.Length;
373 for (int index = 0; index < pars.Length; index ++) {
374 ParameterInfo param = pars [index];
375 if (param.IsOptional)
377 if (index + 1 == pars.Length) {
378 object[] attrs = param.GetCustomAttributes (typeof (System.ParamArrayAttribute), false);
379 if (attrs != null && attrs.Length > 0)
386 // Determines the kind of conversions from argument types to parameter types
387 private ConversionType GetConversionType (ParameterInfo[] parameters, object[] args, string[] names) {
388 int numParams = parameters.Length;
389 int numArgs = args.Length;
390 int numFixedParams = CountStandardParams (parameters);
392 if (numParams == 0) {
394 return ConversionType.Exact;
396 return ConversionType.None;
399 bool usesParamArray = UsesParamArray (parameters);
400 if (numFixedParams == 0 && numArgs == 0)
401 return ConversionType.Exact;
403 if (numArgs < numFixedParams)
404 return ConversionType.None;
406 ConversionType ctype = ConversionType.None;
407 bool isLastParam = false;
408 int paramIndex = 0, argIndex = 0;
409 int [] argOrder = null;
410 if (!CreateArgOrder (parameters, names, numArgs, out argOrder))
411 return ConversionType.None;
413 for (int index = 0; index < numArgs; index ++) {
414 argIndex = argOrder [index];
416 if (paramIndex >= numFixedParams)
417 if (usesParamArray) {
418 paramIndex = parameters.GetUpperBound (0);
422 ConversionType currentCType = ConversionType.None;
424 if (argIndex == -1) {
425 currentCType = ConversionType.Exact;
426 if (ctype < currentCType)
427 ctype = currentCType;
430 if (args [argIndex] != null)
431 type1 = args [argIndex].GetType ();
432 Type type2 = parameters [paramIndex].ParameterType;
434 type2 = type2.GetElementType ();
435 if (usesParamArray && isLastParam) {
437 if (type1.GetElementType () == type2.GetElementType ())
438 currentCType = ConversionType.Exact;
439 else if (ObjectType.IsWideningConversion (type1, type2))
440 currentCType = ConversionType.Widening;
442 currentCType = ConversionType.Narrowing;
444 Type elementType = type2.GetElementType ();
445 if (type1 == elementType)
446 currentCType = ConversionType.Exact;
447 else if (ObjectType.IsWideningConversion (type1, elementType))
448 currentCType = ConversionType.Widening;
450 currentCType = ConversionType.Narrowing;
452 if (currentCType == ConversionType.Narrowing || ctype < currentCType)
453 ctype = currentCType;
456 if (type1 == type2) {
457 currentCType = ConversionType.Exact;
458 if (ctype < currentCType) {
459 ctype = ConversionType.Exact;
461 } else if (ObjectType.IsWideningConversion (type1, type2)) {
462 currentCType = ConversionType.Widening;
463 if (ctype < currentCType)
464 ctype = ConversionType.Widening;
466 ctype = ConversionType.Narrowing;
473 public override object ChangeType(
479 TypeCode src_type = Type.GetTypeCode (value.GetType());
480 TypeCode dest_type = Type.GetTypeCode (myChangeType);
483 case TypeCode.String:
487 return (StringType.FromByte ((byte)value));
488 case TypeCode.UInt16:
490 return (StringType.FromShort ((short)value));
491 case TypeCode.UInt32:
493 return (StringType.FromInteger ((int)value));
494 case TypeCode.UInt64:
496 return (StringType.FromLong ((long)value));
498 return (StringType.FromChar ((char)value));
499 case TypeCode.Single:
500 return (StringType.FromSingle ((float)value));
501 case TypeCode.Double:
502 return (StringType.FromDouble ((double)value));
503 case TypeCode.Boolean:
504 return (StringType.FromBoolean ((bool)value));
505 case TypeCode.Object:
506 return (StringType.FromObject (value));
511 case TypeCode.UInt32:
513 case TypeCode.String:
514 return (IntegerType.FromString ((string)value));
515 case TypeCode.Object:
516 return (IntegerType.FromObject (value));
521 case TypeCode.UInt16:
523 case TypeCode.String:
524 return (ShortType.FromString ((string)value));
525 case TypeCode.Object:
526 return (ShortType.FromObject (value));
529 case TypeCode.Object:
530 return ((Object) value);
535 public override void ReorderArgumentArray(
543 public override MethodBase SelectMethod(
544 BindingFlags bindingAttr,
547 ParameterModifier[] modifiers
553 public override PropertyInfo SelectProperty(
554 BindingFlags bindingAttr,
555 PropertyInfo[] match,
558 ParameterModifier[] modifiers
564 public Object InvokeMember (string name,
570 ParameterModifier[] modifiers,
572 string[] paramNames) {
574 this.objectType = objType;
575 this.bindToName = name;
576 if (name == null || name.Equals ("")) {
577 // Must be a default property
580 object[] attrArray = t.GetCustomAttributes (typeof (DefaultMemberAttribute), false);
581 if (attrArray != null && attrArray.Length != 0) {
582 name = ((DefaultMemberAttribute) attrArray[0]).MemberName;
585 // not found, search in the base type
590 if (name == null || name.Equals (""))
591 throw new MissingMemberException ("No default members defined for type '" + objType + "'");
593 MemberInfo[] memberinfo = GetMembers (objReflect, objType, name, flags);
595 if (memberinfo == null || memberinfo.Length == 0) {
596 throw new MissingMemberException ("No member '" + name + "' defined for type '" + objType + "'");
599 object objState = null;
600 object retVal = null;
601 if (memberinfo [0] is MethodBase) {
602 MethodBase[] methodbase = new MethodBase [memberinfo.Length];
603 for (int index = 0; index < memberinfo.Length; index ++)
604 methodbase [index] = (MethodBase) memberinfo [index];
606 MethodBase mbase = BindToMethod (flags,
613 throw new MissingMemberException ("No member '" + name +
614 "' defined for type '" + objType + "' which takes the given set of arguments");
616 MethodInfo mi = (MethodInfo) mbase;
617 retVal = mi.Invoke (target, args);
618 // Modify the byRefFlags approproately
619 // Also copy the modified arguments back
620 if (objState != null && byRefFlags != null) {
621 BinderState state = (BinderState) objState;
622 object [] originalArgs = state.originalArgs;
623 int[] paramOrder = null;
624 ParameterInfo [] pars = mi.GetParameters ();
625 if (!CreateParamOrder (pars, paramNames, args.Length, out paramOrder))
626 return null; // Should never happen
628 for (int index = 0; index < originalArgs.Length; index++) {
630 if (paramIndex < paramOrder.Length)
631 paramIndex = paramOrder [index];
632 if (paramIndex == -1)
633 continue; // Should not happen
634 if (paramIndex >= pars.Length)
635 paramIndex = pars.GetUpperBound (0);
636 ParameterInfo p = pars [paramIndex];
637 if (p.ParameterType.IsByRef) {
638 if (byRefFlags [index] != false)
639 byRefFlags [index] = true;
640 originalArgs [index] = args [paramIndex];
642 byRefFlags [index] = false;
650 // Determines whether a given method can be invoked with a given set of arguments
651 private bool IsApplicable (MethodBase mb, string [] names, object [] args, ref string errorMsg) {
652 ParameterInfo [] parameters = mb.GetParameters ();
653 int numFixedParams = CountStandardParams (parameters);
654 int numParams = parameters.Length;
657 argCount = args.Length;
659 if (numParams == numFixedParams) // No ParamArray or Optional params
660 if (argCount != numParams)
663 if (argCount < numFixedParams)
666 bool usesParamArray = UsesParamArray (parameters);
667 if (!usesParamArray && (argCount > numParams))
670 if (usesParamArray && (names != null && names.Length > 0)) {
671 errorMsg += "\n\tNamed argument cannot match ParamArray parameters";
675 int paramIndex = 0, argIndex = 0;
676 bool isLastParam = false;
677 int [] argOrder = null;
678 if (!CreateArgOrder (parameters, names, argCount, out argOrder))
681 // We know that we have arguments for all fixed parameters atleast
682 for (int index = 0; index < argCount; index ++) {
684 Type paramType = null;
687 argIndex = argOrder [index];
688 if (argIndex == -1) // Missing argument, we will use the default value.
690 if (index >= numFixedParams)
691 if (usesParamArray) {
692 paramIndex = numParams - 1;
696 paramType = parameters [paramIndex].ParameterType;
697 if (args [argIndex] != null) {
698 argType = args [argIndex].GetType ();
699 if (usesParamArray && isLastParam) {
700 // ParamArray parameter of type 'T'. We can either have an
701 // argument which is an array of type T, or 'n' number of
702 // arguments that are of/convertible to type 'T'
703 if (!argType.IsArray) {
704 Type elementType = paramType.GetElementType ();
705 if (!ObjectType.ImplicitConversionExists (argType, elementType))
708 Type elementType = paramType.GetElementType ();
709 argType = argType.GetElementType ();
710 if (!elementType.IsAssignableFrom (argType))
714 if (paramType.IsByRef)
715 paramType = paramType.GetElementType ();
716 if (!ObjectType.ImplicitConversionExists (argType, paramType))
726 // Creates argument order
727 // If argument names are present, then argument order is created according to paramters
728 // For missing arguments, the corresponding entry wil be -1
729 // For example, if a method 'F (a As Integer,b As Integer,c As Integer,d As Integer)'
730 // is invoked like 'F (c := 1, a := 2, d :=3), then the argument order will be
732 // This method also checks for duplicate argument names, missing parameters, etc.
734 // If no argument names are present, the order of arguments is expected to match that
735 // of the parameters. So, in this case, the order will be {0, 1, 2, 3...., numArgs - 1}
736 private bool CreateArgOrder (ParameterInfo [] pars, string [] names, int numArgs, out int [] argOrder)
739 if (names == null || names.Length == 0) {
740 argOrder = new int [numArgs];
741 for (int index = 0; index < numArgs; index ++)
742 argOrder [index] = index;
745 int numParamsMatched = 0;
746 argOrder = new int [pars.Length];
747 for (int index = 0; index < argOrder.Length; index ++)
748 argOrder [index] = -1;
749 for (int paramIndex = 0; paramIndex < pars.Length; paramIndex ++) {
750 string paramName = pars [paramIndex].Name.ToLower ();
751 bool foundArgForParam = false;
752 for (int argindex = 0; argindex < names.Length; argindex ++) {
753 string argName = names [argindex].ToLower ();
754 if (paramName.Equals (argName)) {
755 foundArgForParam = true;
756 if (argOrder [paramIndex] != -1)
757 throw new ArgumentException ("Argument '" +
758 argName + "' specified multiple times");
759 argOrder [paramIndex] = argindex;
764 if (!foundArgForParam && !pars [paramIndex].IsOptional)
768 if (numParamsMatched != numArgs)
769 return false; // We have some invalid paramnames
774 // Creates parameter order
775 // Similar to CreateArgOrder method, but here order is created according to names/arguments
776 private bool CreateParamOrder (ParameterInfo [] pars, string [] names, int numArgs, out int [] paramOrder)
779 if (names == null || names.Length == 0) {
780 paramOrder = new int [numArgs];
781 for (int index = 0; index < numArgs; index ++)
782 paramOrder [index] = index;
785 paramOrder = new int [names.Length];
786 for (int index = 0; index < paramOrder.Length; index ++)
787 paramOrder [index] = -1;
788 for (int argindex = 0; argindex < names.Length; argindex ++) {
789 string argName = names [argindex].ToLower ();
790 bool foundParamForArg = false;
791 for (int paramIndex = 0; paramIndex < pars.Length; paramIndex ++) {
792 string paramName = pars [paramIndex].Name.ToLower ();
793 if (paramName.Equals (argName)) {
794 paramOrder [argindex] = paramIndex;
795 foundParamForArg = true;
797 if (! foundParamForArg)
805 private static MemberInfo [] GetMostDerivedMembers (ArrayList memberinfo) {
807 int numElementsEliminated = 0;
808 for (i = 0; i < memberinfo.Count; i++) {
809 MemberInfo mi = (MemberInfo) memberinfo [i];
810 for (int j = i + 1; j < memberinfo.Count; j++) {
811 bool eliminateBaseMembers = false;
812 MemberInfo thisMember = (MemberInfo) memberinfo [j];
813 Type t1 = mi.DeclaringType;
814 Type t2 = thisMember.DeclaringType;
815 if (mi.MemberType == MemberTypes.Field)
816 eliminateBaseMembers = true;
817 if (mi.MemberType == MemberTypes.Method) {
818 MethodInfo methodinfo = (MethodInfo) mi;
819 if (methodinfo.IsVirtual)
820 eliminateBaseMembers = true;
822 if (mi.MemberType == MemberTypes.Property) {
823 PropertyInfo propertyinfo = (PropertyInfo) mi;
824 MethodInfo method = propertyinfo.GetGetMethod ();
825 if (method.IsVirtual)
826 eliminateBaseMembers = true;
828 if (eliminateBaseMembers) {
829 if (t1.IsSubclassOf (t2)) {
830 memberinfo [j] = null;
831 numElementsEliminated ++;
832 } else if (t2.IsSubclassOf (t1)) {
833 memberinfo [i] = null;
834 numElementsEliminated ++;
840 MemberInfo [] newMemberList = new MemberInfo [memberinfo.Count - numElementsEliminated];
842 for (int index = 0; index < memberinfo.Count; index ++) {
843 if (memberinfo [index] != null) {
844 newMemberList [newIndex ++] = (MemberInfo) memberinfo [index];
847 return newMemberList;
850 internal MemberInfo [] GetMembers (IReflect objReflect, Type objType, string name, BindingFlags invokeFlags)
852 MemberInfo [] mi = objReflect.GetMember (name, invokeFlags);
853 if (mi == null || mi.Length == 0)
856 for (int index = 0; index < mi.Length; index ++)
858 if (mi [index].MemberType == MemberTypes.Property) {
859 PropertyInfo propinfo = (PropertyInfo) mi [index];
860 if ((invokeFlags & BindingFlags.GetProperty) == BindingFlags.GetProperty)
861 mi [index] = propinfo.GetGetMethod ();
862 else if ((invokeFlags & BindingFlags.SetProperty) == BindingFlags.SetProperty)
863 mi [index] = propinfo.GetSetMethod ();