private static TypeTree BuildTypeTree(TypeTree root, Type[] types) { IEnumerable <Type> subclassTypes = types.Where((type) => type.IsSubclassOf(root.Type)).OrderBy(o => o.FullName, invariantComparer); foreach (Type subclassType in subclassTypes) { root.Subclasses[ContractEnforcement.GenerateNameWithClassAttributes(subclassType)] = ContractEnforcement.BuildTypeTree(new TypeTree(subclassType), types); } IEnumerable <KeyValuePair <string, MemberInfo> > memberInfos = root.Type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) .Select(memberInfo => new KeyValuePair <string, MemberInfo>($"{memberInfo.ToString()}{string.Join("-", ContractEnforcement.RemoveDebugSpecificAttributes(memberInfo.CustomAttributes))}", memberInfo)) .OrderBy(o => o.Key, invariantComparer); foreach (KeyValuePair <string, MemberInfo> memberInfo in memberInfos) { List <string> attributes = ContractEnforcement.RemoveDebugSpecificAttributes(memberInfo.Value.CustomAttributes) .Select((customAttribute) => customAttribute.AttributeType.Name) .ToList(); attributes.Sort(invariantComparer); string methodSignature = null; if (memberInfo.Value.MemberType == MemberTypes.Method) { MethodInfo methodInfo = (MethodInfo)memberInfo.Value; methodSignature = ContractEnforcement.GenerateNameWithMethodAttributes(methodInfo); } else if (memberInfo.Value.MemberType == MemberTypes.Property) { PropertyInfo propertyInfo = (PropertyInfo)memberInfo.Value; methodSignature = ContractEnforcement.GenerateNameWithPropertyAttributes(propertyInfo); } else if (memberInfo.Value.MemberType == MemberTypes.Field) { FieldInfo fieldInfo = (FieldInfo)memberInfo.Value; methodSignature = ContractEnforcement.GenerateNameWithFieldAttributes(fieldInfo); } else if (memberInfo.Value.MemberType == MemberTypes.Constructor || memberInfo.Value.MemberType == MemberTypes.Event) { methodSignature = memberInfo.ToString(); } root.Members[ memberInfo.Key ] = new MemberMetadata( memberInfo.Value.MemberType, attributes, methodSignature); } foreach (Type nestedType in root.Type.GetNestedTypes().OrderBy(o => o.FullName)) { root.NestedTypes[ContractEnforcement.GenerateNameWithClassAttributes(nestedType)] = ContractEnforcement.BuildTypeTree(new TypeTree(nestedType), types); } return(root); }
private static string GenerateNameWithPropertyAttributes(PropertyInfo propertyInfo) { string name = $"{propertyInfo};{nameof(propertyInfo.CanRead)}:{(propertyInfo.CanRead ? bool.TrueString : bool.FalseString)};" + $"{nameof(propertyInfo.CanWrite)}:{(propertyInfo.CanWrite ? bool.TrueString : bool.FalseString)};"; MethodInfo getMethodInfo = propertyInfo.GetGetMethod(); if (getMethodInfo != null) { name += ContractEnforcement.GenerateNameWithMethodAttributes(getMethodInfo); } MethodInfo setMethodInfo = propertyInfo.GetSetMethod(); if (setMethodInfo != null) { name += ContractEnforcement.GenerateNameWithMethodAttributes(setMethodInfo); } return(name); }
private static TypeTree BuildTypeTree(TypeTree root, Type[] types) { IEnumerable <Type> subclassTypes = types.Where((type) => type.IsSubclassOf(root.Type)).OrderBy(o => o.FullName, invariantComparer); foreach (Type subclassType in subclassTypes) { root.Subclasses[ContractEnforcement.GenerateNameWithClassAttributes(subclassType)] = ContractEnforcement.BuildTypeTree(new TypeTree(subclassType), types); } IEnumerable <KeyValuePair <string, MemberInfo> > memberInfos = root.Type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) .Select(memberInfo => new KeyValuePair <string, MemberInfo>($"{memberInfo}{string.Join("-", ContractEnforcement.RemoveDebugSpecificAttributes(memberInfo.CustomAttributes))}", memberInfo)) .OrderBy(o => o.Key, invariantComparer); foreach (KeyValuePair <string, MemberInfo> memberInfo in memberInfos) { List <string> attributes = ContractEnforcement.RemoveDebugSpecificAttributes(memberInfo.Value.CustomAttributes) .Select((customAttribute) => customAttribute.AttributeType.Name) .ToList(); attributes.Sort(invariantComparer); string methodSignature = null; if (memberInfo.Value.MemberType == MemberTypes.Method) { MethodInfo methodInfo = (MethodInfo)memberInfo.Value; methodSignature = ContractEnforcement.GenerateNameWithMethodAttributes(methodInfo); } else if (memberInfo.Value.MemberType == MemberTypes.Property) { PropertyInfo propertyInfo = (PropertyInfo)memberInfo.Value; methodSignature = ContractEnforcement.GenerateNameWithPropertyAttributes(propertyInfo); } else if (memberInfo.Value.MemberType == MemberTypes.Field) { FieldInfo fieldInfo = (FieldInfo)memberInfo.Value; methodSignature = ContractEnforcement.GenerateNameWithFieldAttributes(fieldInfo); } else if (memberInfo.Value.MemberType == MemberTypes.Constructor || memberInfo.Value.MemberType == MemberTypes.Event) { methodSignature = memberInfo.ToString(); } // Certain custom attributes add the following to the string value "d__9" which sometimes changes // based on the .NET SDK version it is being built on. This removes the value to avoid showing // breaking change when there is none. string key = Regex.Replace(memberInfo.Key, @"d__\d+", string.Empty); root.Members[ key ] = new MemberMetadata( memberInfo.Value.MemberType, attributes, methodSignature); } foreach (Type nestedType in root.Type.GetNestedTypes().OrderBy(o => o.FullName)) { root.NestedTypes[ContractEnforcement.GenerateNameWithClassAttributes(nestedType)] = ContractEnforcement.BuildTypeTree(new TypeTree(nestedType), types); } return(root); }