/// <summary> /// Provides an implementation of __contains__. We can pull contains from: /// ICollection of T which defines Contains directly /// IList which defines Contains directly /// IDictionary which defines Contains directly /// IDictionary of K,V which defines Contains directly /// IEnumerable of K which we have an InstaceOps helper for /// IEnumerable which we have an instance ops helper for /// IEnumerator of K which we have an InstanceOps helper for /// IEnumerator which we have an instance ops helper for /// /// String is ignored here because it defines __contains__ via extension methods already. /// /// The lookup is well ordered and not dependent upon the order of values returned by reflection. /// </summary> private static MemberGroup/*!*/ ContainsResolver(MemberBinder/*!*/ binder, Type/*!*/ type) { if (type == typeof(PythonGenerator)) { // it's enumerable but doesn't have __contains__ return MemberGroup.EmptyGroup; } List<MemberTracker> containsMembers = null; IList<Type> intf = binder.GetInterfaces(type); // if we get a __contains__ for something w/ a generic typed to object don't look for non-generic versions bool hasObjectContains = false; // search for IDictionary<K, V> first because it's ICollection<KVP<K, V>> and we want to call ContainsKey foreach (Type t in intf) { if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IDictionary<,>)) { if (t.GetGenericArguments()[0] == typeof(object)) { hasObjectContains = true; } if (containsMembers == null) { containsMembers = new List<MemberTracker>(); } containsMembers.Add(MethodTracker.FromMemberInfo(t.GetMethod("ContainsKey"))); } } if (containsMembers == null) { // then look for ICollection<T> for generic __contains__ first if we're not an IDictionary<K, V> foreach (Type t in intf) { if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(ICollection<>)) { if (t.GetGenericArguments()[0] == typeof(object)) { hasObjectContains = true; } if (containsMembers == null) { containsMembers = new List<MemberTracker>(); } containsMembers.Add(MethodTracker.FromMemberInfo(t.GetMethod("Contains"))); } } } if (!hasObjectContains) { // look for non-generic contains if we didn't already find an overload which takes // object if (intf.Contains(typeof(IList))) { if (containsMembers == null) { containsMembers = new List<MemberTracker>(); } containsMembers.Add(MethodTracker.FromMemberInfo(typeof(IList).GetMethod("Contains"))); } else if (intf.Contains(typeof(IDictionary))) { if (containsMembers == null) { containsMembers = new List<MemberTracker>(); } containsMembers.Add(MethodTracker.FromMemberInfo(typeof(IDictionary).GetMethod("Contains"))); } else if (containsMembers == null) { // see if we can produce a contains for IEnumerable GetEnumeratorContains(type, intf, ref containsMembers, ref hasObjectContains, typeof(IEnumerable<>), typeof(IEnumerable), String.Empty); if (containsMembers == null) { GetEnumeratorContains(type, intf, ref containsMembers, ref hasObjectContains, typeof(IEnumerator<>), typeof(IEnumerator), "IEnumerator"); } } } if (containsMembers != null) { return new MemberGroup(containsMembers.ToArray()); } return MemberGroup.EmptyGroup; }
/// <summary> /// Provides a resolution for __len__ /// </summary> private static MemberGroup/*!*/ LengthResolver(MemberBinder/*!*/ binder, Type/*!*/ type) { if (binder.GetInterfaces(type).Contains(typeof(ICollection))) { return GetInstanceOpsMethod(type, "LengthMethod"); } foreach (Type t in binder.GetInterfaces(type)) { if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(ICollection<>)) { MethodInfo genMeth = typeof(InstanceOps).GetMethod("GenericLengthMethod"); return new MemberGroup( MethodTracker.FromMemberInfo(genMeth.MakeGenericMethod(t.GetGenericArguments()), type) ); } } return MemberGroup.EmptyGroup; }