/// <summary> Returns the element type of any class implementing <see cref="IEnumerable{T}" /> interface. Returns null when it is not found. </summary> public static TypeReference GetElementTypeFromIEnumerable(this SpecializedType collectionType, MetadataContext cx, bool allowIEnumerator, out bool?isGeneric) { bool foundNonGenericIEnumerable = false; foreach (var baseType in cx.GetBaseTypes(collectionType)) { if (baseType.Type == TypeSignature.IEnumerableOfT || (allowIEnumerator && baseType.Type == TypeSignature.IEnumeratorOfT)) { isGeneric = true; return(Assert.Single(baseType.TypeArguments)); } if (baseType.Type == TypeSignature.IEnumerable || (allowIEnumerator && baseType.Type == TypeSignature.IEnumerator)) { foundNonGenericIEnumerable = true; } } // System.Collections.IEnumerable found in type hierarchy -> Object is element type. if (foundNonGenericIEnumerable) { isGeneric = false; return(TypeSignature.Object); } isGeneric = null; return(null); }
public static TypeDef AutoResolveImplementations(TypeDef type, MetadataContext cx) { var thisType = type.Signature.SpecializeByItself(); var baseTypes = cx.GetBaseTypes(thisType).ToArray(); var interfaces = cx.GetDirectImplements(thisType).ToArray(); // exclude methods and properties that are already implemented var explicitImplMethods = new HashSet <MethodSignature>(type.Members.OfType <MethodDef>().SelectMany(m => m.Implements).Select(m => m.Signature)); var explicitImplProps = new HashSet <PropertySignature>(type.Members.OfType <PropertyDef>().SelectMany(m => m.Implements).Select(m => m.Signature)); var methods = baseTypes.Concat(interfaces).ZipSelectMany(t => cx.GetMemberMethodDefs(t.Type).Where(m => !explicitImplMethods.Contains(m))).ToLookup(m => m.Item2.Name); var properties = baseTypes.Concat(interfaces).ZipSelectMany(t => cx.GetMemberPropertyDefs(t.Type).Where(p => !explicitImplProps.Contains(p))).ToLookup(p => p.Item2.Name); var myMembers = type.Members.Select(member => { // implementations must be public if (member is MethodDef method && methods.Contains(method.Signature.Name)) { var mm = methods[method.Signature.Name] .Where(m2 => m2.Item2.Params.Select(p => p.Type).SequenceEqual(method.Signature.Params.Select(p => p.Type))) .Where(m2 => m2.Item2.ResultType == method.Signature.ResultType) .Where(m2 => method.Signature.Accessibility == m2.Item2.Accessibility) .Where(m2 => method.Signature.IsOverride || m2.Item2.DeclaringType.Kind == "interface") .ToArray(); return(method.With(implements: method.Implements.AddRange(mm.Select(m => m.Item2.Specialize(m.Item1.TypeArguments, m.Item2.TypeParameters.Select(TypeReference.GenericParameter)))))); }
/// <summary> /// Gets whether this type definition is derived from the base type definition. /// </summary> public static bool IsDerivedFrom(this SpecializedType type, SpecializedType baseType, MetadataContext cx) { if (type == null) { throw new ArgumentNullException("type"); } if (baseType == null) { return(false); } return(cx.GetBaseTypes(type).Contains(baseType)); }