private void GetParametrizedNames(ReflectedTypeInfo type, StringBuilder builder, Queue <ReflectedParameterTypeInfo> parameterQueue, bool isEntry) { if (type == null) { return; } GetParametrizedNames(type.DeclaringType, builder, parameterQueue, false); builder.Append(type.AliasedName); if (IsGenericType) { var paramCount = type.LocalGenericParameters.Count(); if (paramCount > 0) { builder.Append("<"); bool first = true; for (int i = 0; i < paramCount; i++) { if (!first) { builder.Append(","); } var param = parameterQueue.Dequeue(); builder.Append(param.DisplayName); first = false; } builder.Append(">"); } } if (!isEntry) { builder.Append("."); } }
private void GetParametrizedNames(ReflectedTypeInfo type, StringBuilder builder, Queue<ReflectedParameterTypeInfo> parameterQueue, bool isEntry) { if(type == null) { return; } GetParametrizedNames(type.DeclaringType, builder, parameterQueue,false); builder.Append(type.AliasedName); if(IsGenericType) { var paramCount = type.LocalGenericParameters.Count(); if(paramCount > 0) { builder.Append("<"); bool first = true; for(int i = 0; i < paramCount; i++) { if(!first) { builder.Append(","); } var param = parameterQueue.Dequeue(); builder.Append(param.DisplayName); first = false; } builder.Append(">"); } } if(!isEntry) { builder.Append("."); } }
private void GetNameSignatures(ReflectedTypeInfo type, StringBuilder builder, Queue <ReflectedParameterTypeInfo> parameterQueue) { if (type == null) { return; } GetNameSignatures(type.DeclaringType, builder, parameterQueue); builder.Append("."); builder.Append(type.Name); if (IsGenericType) { var paramCount = type.LocalGenericParameters.Count(); if (paramCount > 0) { builder.Append("{"); bool first = true; for (int i = 0; i < paramCount; i++) { if (!first) { builder.Append(","); } var param = parameterQueue.Dequeue(); builder.Append(param.Signature); first = false; } builder.Append("}"); } } }
private ReflectedMethodInfo BuildMethodInfo(ReflectedTypeInfo typeInfo, MethodInfo method) { var isNewSlot = ((method.Attributes & MethodAttributes.NewSlot) == MethodAttributes.NewSlot); var isReusedSlot = ((method.Attributes & MethodAttributes.ReuseSlot) == MethodAttributes.ReuseSlot); var isOverride = method.IsVirtual && !isNewSlot && isReusedSlot; var methodInfo = new ReflectedMethodInfo() { Name = method.Name, Type = typeInfo, DeclaringType = GetType(method.DeclaringType), IsOverride = isOverride, MemberAccess = DetermineAccess(method), IsVirtual = method.IsVirtual && !isOverride, IsStatic = method.IsStatic, IsExtensionMethod = method.GetCustomAttributes(typeof(ExtensionAttribute), false).Any() }; var parameterBuilder = new ParameterBuilder(methodInfo, GetType); if (method.IsGenericMethod) { var genericArgs = method.GetGenericArguments(); methodInfo.IsGenericMethod = true; methodInfo.GenericParameters = GetGenericParameters(genericArgs, true); for (int i = 0; i < genericArgs.Length; i++) { foreach (var constraintType in genericArgs[i].GetGenericParameterConstraints()) { if (constraintType == typeof(ValueType)) { continue; } methodInfo.GenericParameters[i].Types.Add(parameterBuilder.BuildType(constraintType)); } } } methodInfo.ReturnType = parameterBuilder.BuildType(method.ReturnType); methodInfo.Parameters = GetParameters(method.GetParameters(), parameterBuilder); if (methodInfo.IsExtensionMethod) { methodInfo.Parameters[0].IsExtensionParameter = true; } return(methodInfo); }
private void GetNameSignatures(ReflectedTypeInfo type, StringBuilder builder, Queue<ReflectedParameterTypeInfo> parameterQueue) { if(type == null) { return; } GetNameSignatures(type.DeclaringType, builder, parameterQueue); builder.Append("."); builder.Append(type.Name); if(IsGenericType) { var paramCount = type.LocalGenericParameters.Count(); if(paramCount > 0) { builder.Append("{"); bool first = true; for(int i = 0; i < paramCount; i++) { if(!first) { builder.Append(","); } var param = parameterQueue.Dequeue(); builder.Append(param.Signature); first = false; } builder.Append("}"); } } }
private void BuildType(Type type, ReflectedTypeInfo typeInfo) { _builtTypes.Add(type); _documentedTypes.Add(typeInfo); var typeParameterBuilder = new ParameterBuilder(typeInfo, GetType); if (type.IsGenericType) { var genericTypeArguments = type.GetGenericArguments(); typeInfo.IsGeneric = true; typeInfo.GenericParameters = GetGenericParameters(genericTypeArguments, false); // since generic parameter constraints can refer to each other and parameterBuilder.BuildType gets these references // by retrieving the registered instance of the type, building the types for GenericParameters has to occur after // the skeleton is built and assigned to the typeInfo instance. for (int i = 0; i < genericTypeArguments.Length; i++) { foreach (var constraintType in genericTypeArguments[i].GetGenericParameterConstraints()) { if (constraintType == typeof(ValueType)) { continue; } typeInfo.GenericParameters[i].Types.Add(typeParameterBuilder.BuildType(constraintType)); } } } typeInfo.BaseType = typeParameterBuilder.BuildType(type.BaseType); typeInfo.Interfaces = (from i in type.GetInterfaces() where !i.Name.StartsWith("_") select typeParameterBuilder.BuildType(i)).ToList(); if (typeInfo.IsDelegate) { return; } // find constructors foreach (var constructor in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { if (constructor.IsPrivate || constructor.IsAssembly) { continue; } var isProtected = constructor.IsFamily && !constructor.IsPublic && !constructor.IsPrivate; var constructorInfo = new ReflectedConstructorInfo() { Type = typeInfo, IsStatic = constructor.IsStatic, MemberAccess = isProtected ? MemberAccess.Protected : MemberAccess.Public, DeclaringType = GetType(constructor.DeclaringType), }; constructorInfo.Parameters = GetParameters(constructor.GetParameters(), typeParameterBuilder); typeInfo.Constructors.Add(constructorInfo); } // find methods foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { if (method.IsSpecialName || method.IsPrivate || method.IsAssembly || method.Name == "Finalize") { continue; } var methodInfo = BuildMethodInfo(typeInfo, method); typeInfo.Methods.Add(methodInfo); } // find properties foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { var getMethod = property.GetGetMethod(true); var setMethod = property.GetSetMethod(true); if ((getMethod == null || getMethod.IsPrivate || getMethod.IsAssembly) && (setMethod == null || setMethod.IsPrivate || setMethod.IsAssembly) ) { continue; } var accessorMethod = getMethod == null || getMethod.IsPrivate ? setMethod : getMethod; var methodInfo = BuildMethodInfo(typeInfo, accessorMethod); var propertyInfo = new ReflectedPropertyInfo() { Name = property.Name, IsIndexer = property.Name == "Item", Type = typeInfo, DeclaringType = GetType(property.DeclaringType), ReturnType = typeParameterBuilder.BuildType(property.PropertyType), IsOverride = methodInfo.IsOverride, IsStatic = methodInfo.IsStatic, IsVirtual = methodInfo.IsVirtual, GetAccess = DetermineAccess(getMethod), SetAccess = DetermineAccess(setMethod) }; propertyInfo.MemberAccess = propertyInfo.GetAccess == MemberAccess.Public || propertyInfo.SetAccess == MemberAccess.Public ? MemberAccess.Public : MemberAccess.Protected; if (propertyInfo.IsIndexer) { methodInfo.Name = "Item"; propertyInfo.IndexerParameters = GetParameters(property.GetIndexParameters(), typeParameterBuilder); } typeInfo.Properties.Add(propertyInfo); } // find fields foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { if (field.IsPrivate || field.IsAssembly) { continue; } var isProtected = field.IsFamily && !field.IsPublic && !field.IsPrivate; var fieldInfo = new ReflectedFieldInfo() { Name = field.Name, Type = typeInfo, IsStatic = field.IsStatic, MemberAccess = isProtected ? MemberAccess.Protected : MemberAccess.Public, DeclaringType = GetType(field.DeclaringType), ReturnType = typeParameterBuilder.BuildType(field.FieldType) }; typeInfo.Fields.Add(fieldInfo); } // find events foreach (var ev in type.GetEvents(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { var addMethod = ev.GetAddMethod(true); var removeMethod = ev.GetRemoveMethod(true); if ((addMethod == null || addMethod.IsPrivate || addMethod.IsAssembly) && (removeMethod == null || removeMethod.IsPrivate || removeMethod.IsAssembly) ) { continue; } var accessorMethod = addMethod == null || addMethod.IsPrivate ? removeMethod : addMethod; var methodInfo = BuildMethodInfo(typeInfo, accessorMethod); var eventInfo = new ReflectedEventInfo() { Name = ev.Name, Type = typeInfo, DeclaringType = GetType(ev.DeclaringType), ReturnType = typeParameterBuilder.BuildType(ev.EventHandlerType), IsOverride = methodInfo.IsOverride, IsStatic = methodInfo.IsStatic, IsVirtual = methodInfo.IsVirtual, AddAccess = DetermineAccess(addMethod), RemoveAccess = DetermineAccess(removeMethod) }; typeInfo.Events.Add(eventInfo); } }
private ReflectedTypeInfo GetType(Type type, bool build) { if (type == null) { return(null); } var qualifiedName = type.ToString(); if (type.IsGenericType) { qualifiedName = type.GetGenericTypeDefinition().ToString(); } ReflectedTypeInfo typeInfo = null; if (!_seenTypes.TryGetValue(qualifiedName, out typeInfo)) { if (!type.IsArray) { if (type.IsGenericType) { _typesToBuild.Enqueue(type.GetGenericTypeDefinition()); } else { _typesToBuild.Enqueue(type); } } var simpleName = type.Name; if (type.IsGenericType) { var tickIndex = type.Name.IndexOf('`'); if (tickIndex > 0) { simpleName = type.Name.Substring(0, tickIndex); } } typeInfo = new ReflectedTypeInfo() { Assembly = type.Assembly.GetName().Name, Name = simpleName, Namespace = type.Namespace, IsDelegate = typeof(Delegate).IsAssignableFrom(type), Kind = type.IsInterface ? TypeKind.Interface : (type.IsValueType && !type.IsClass) ? TypeKind.Struct : type.IsEnum ? TypeKind.Enum : TypeKind.Class, IsAbstract = type.IsAbstract && !type.IsSealed, IsStatic = type.IsAbstract && type.IsSealed, IsSealed = type.IsSealed && !type.IsAbstract }; if (type.DeclaringType != null) { typeInfo.DeclaringType = GetType(type.DeclaringType); } _seenTypes[qualifiedName] = typeInfo; } if (build) { BuildType(type, typeInfo); } return(typeInfo); }
private ReflectedMethodInfo BuildMethodInfo(ReflectedTypeInfo typeInfo, MethodInfo method) { var isNewSlot = ((method.Attributes & MethodAttributes.NewSlot) == MethodAttributes.NewSlot); var isReusedSlot = ((method.Attributes & MethodAttributes.ReuseSlot) == MethodAttributes.ReuseSlot); var isOverride = method.IsVirtual && !isNewSlot && isReusedSlot; var methodInfo = new ReflectedMethodInfo() { Name = method.Name, Type = typeInfo, DeclaringType = GetType(method.DeclaringType), IsOverride = isOverride, MemberAccess = DetermineAccess(method), IsVirtual = method.IsVirtual && !isOverride, IsStatic = method.IsStatic, IsExtensionMethod = method.GetCustomAttributes(typeof(ExtensionAttribute), false).Any() }; var parameterBuilder = new ParameterBuilder(methodInfo, GetType); if(method.IsGenericMethod) { var genericArgs = method.GetGenericArguments(); methodInfo.IsGenericMethod = true; methodInfo.GenericParameters = GetGenericParameters(genericArgs, true); for(int i = 0; i < genericArgs.Length; i++) { foreach(var constraintType in genericArgs[i].GetGenericParameterConstraints()) { if(constraintType == typeof(ValueType)) { continue; } methodInfo.GenericParameters[i].Types.Add(parameterBuilder.BuildType(constraintType)); } } } methodInfo.ReturnType = parameterBuilder.BuildType(method.ReturnType); methodInfo.Parameters = GetParameters(method.GetParameters(), parameterBuilder); if(methodInfo.IsExtensionMethod) { methodInfo.Parameters[0].IsExtensionParameter = true; } return methodInfo; }
private void BuildType(Type type, ReflectedTypeInfo typeInfo) { _builtTypes.Add(type); _documentedTypes.Add(typeInfo); var typeParameterBuilder = new ParameterBuilder(typeInfo, GetType); if(type.IsGenericType) { var genericTypeArguments = type.GetGenericArguments(); typeInfo.IsGeneric = true; typeInfo.GenericParameters = GetGenericParameters(genericTypeArguments, false); // since generic parameter constraints can refer to each other and parameterBuilder.BuildType gets these references // by retrieving the registered instance of the type, building the types for GenericParameters has to occur after // the skeleton is built and assigned to the typeInfo instance. for(int i = 0; i < genericTypeArguments.Length; i++) { foreach(var constraintType in genericTypeArguments[i].GetGenericParameterConstraints()) { if(constraintType == typeof(ValueType)) { continue; } typeInfo.GenericParameters[i].Types.Add(typeParameterBuilder.BuildType(constraintType)); } } } typeInfo.BaseType = typeParameterBuilder.BuildType(type.BaseType); typeInfo.Interfaces = (from i in type.GetInterfaces() where !i.Name.StartsWith("_") select typeParameterBuilder.BuildType(i)).ToList(); if(typeInfo.IsDelegate) { return; } // find constructors foreach(var constructor in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { if(constructor.IsPrivate || constructor.IsAssembly) { continue; } var isProtected = constructor.IsFamily && !constructor.IsPublic && !constructor.IsPrivate; var constructorInfo = new ReflectedConstructorInfo() { Type = typeInfo, IsStatic = constructor.IsStatic, MemberAccess = isProtected ? MemberAccess.Protected : MemberAccess.Public, DeclaringType = GetType(constructor.DeclaringType), }; constructorInfo.Parameters = GetParameters(constructor.GetParameters(), typeParameterBuilder); typeInfo.Constructors.Add(constructorInfo); } // find methods foreach(var method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { if(method.IsSpecialName || method.IsPrivate || method.IsAssembly || method.Name == "Finalize") { continue; } var methodInfo = BuildMethodInfo(typeInfo, method); typeInfo.Methods.Add(methodInfo); } // find properties foreach(var property in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { var getMethod = property.GetGetMethod(true); var setMethod = property.GetSetMethod(true); if((getMethod == null || getMethod.IsPrivate || getMethod.IsAssembly) && (setMethod == null || setMethod.IsPrivate || setMethod.IsAssembly) ) { continue; } var accessorMethod = getMethod == null || getMethod.IsPrivate ? setMethod : getMethod; var methodInfo = BuildMethodInfo(typeInfo, accessorMethod); var propertyInfo = new ReflectedPropertyInfo() { Name = property.Name, IsIndexer = property.Name == "Item", Type = typeInfo, DeclaringType = GetType(property.DeclaringType), ReturnType = typeParameterBuilder.BuildType(property.PropertyType), IsOverride = methodInfo.IsOverride, IsStatic = methodInfo.IsStatic, IsVirtual = methodInfo.IsVirtual, GetAccess = DetermineAccess(getMethod), SetAccess = DetermineAccess(setMethod) }; propertyInfo.MemberAccess = propertyInfo.GetAccess == MemberAccess.Public || propertyInfo.SetAccess == MemberAccess.Public ? MemberAccess.Public : MemberAccess.Protected; if(propertyInfo.IsIndexer) { methodInfo.Name = "Item"; propertyInfo.IndexerParameters = GetParameters(property.GetIndexParameters(), typeParameterBuilder); } typeInfo.Properties.Add(propertyInfo); } // find fields foreach(var field in type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { if(field.IsPrivate || field.IsAssembly) { continue; } var isProtected = field.IsFamily && !field.IsPublic && !field.IsPrivate; var fieldInfo = new ReflectedFieldInfo() { Name = field.Name, Type = typeInfo, IsStatic = field.IsStatic, MemberAccess = isProtected ? MemberAccess.Protected : MemberAccess.Public, DeclaringType = GetType(field.DeclaringType), ReturnType = typeParameterBuilder.BuildType(field.FieldType) }; typeInfo.Fields.Add(fieldInfo); } // find events foreach(var ev in type.GetEvents(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { var addMethod = ev.GetAddMethod(true); var removeMethod = ev.GetRemoveMethod(true); if((addMethod == null || addMethod.IsPrivate || addMethod.IsAssembly) && (removeMethod == null || removeMethod.IsPrivate || removeMethod.IsAssembly) ) { continue; } var accessorMethod = addMethod == null || addMethod.IsPrivate ? removeMethod : addMethod; var methodInfo = BuildMethodInfo(typeInfo, accessorMethod); var eventInfo = new ReflectedEventInfo() { Name = ev.Name, Type = typeInfo, DeclaringType = GetType(ev.DeclaringType), ReturnType = typeParameterBuilder.BuildType(ev.EventHandlerType), IsOverride = methodInfo.IsOverride, IsStatic = methodInfo.IsStatic, IsVirtual = methodInfo.IsVirtual, AddAccess = DetermineAccess(addMethod), RemoveAccess = DetermineAccess(removeMethod) }; typeInfo.Events.Add(eventInfo); } }
private ReflectedTypeInfo GetType(Type type, bool build) { if(type == null) { return null; } var qualifiedName = type.ToString(); if(type.IsGenericType) { qualifiedName = type.GetGenericTypeDefinition().ToString(); } ReflectedTypeInfo typeInfo = null; if(!_seenTypes.TryGetValue(qualifiedName, out typeInfo)) { if(!type.IsArray) { if(type.IsGenericType) { _typesToBuild.Enqueue(type.GetGenericTypeDefinition()); } else { _typesToBuild.Enqueue(type); } } var simpleName = type.Name; if(type.IsGenericType) { var tickIndex = type.Name.IndexOf('`'); if(tickIndex > 0) { simpleName = type.Name.Substring(0, tickIndex); } } typeInfo = new ReflectedTypeInfo() { Assembly = type.Assembly.GetName().Name, Name = simpleName, Namespace = type.Namespace, IsDelegate = typeof(Delegate).IsAssignableFrom(type), Kind = type.IsInterface ? TypeKind.Interface : (type.IsValueType && !type.IsClass) ? TypeKind.Struct : type.IsEnum ? TypeKind.Enum : TypeKind.Class, IsAbstract = type.IsAbstract && !type.IsSealed, IsStatic = type.IsAbstract && type.IsSealed, IsSealed = type.IsSealed && !type.IsAbstract }; if(type.DeclaringType != null) { typeInfo.DeclaringType = GetType(type.DeclaringType); } _seenTypes[qualifiedName] = typeInfo; } if(build) { BuildType(type, typeInfo); } return typeInfo; }
private void AddMemberTables(XDoc html, ReflectedTypeInfo type) { if(!type.Constructors.Any() && !type.Fields.Any() && !type.Properties.Any() && !type.Methods.Any() && !type.Events.Any()) { return; } html.StartSection(1, "members", "Members"); if(type.Constructors.Any()) { html.StartSection(2, "ctors", "Constructors") .Start("table") .Start("tr").Elem("th", "Visibility").Elem("th", "Description").End(); foreach(var member in type.Constructors.OrderBy(x => x.DisplayName)) { BuildConstructorRow(html, member); } html.End() // table .EndSection(); } if(type.Fields.Any()) { html.StartSection(2, "fields", "Fields") .Start("table") .Start("tr").Elem("th", "Visibility").Elem("th", "Description").End(); foreach(var member in type.Fields.OrderBy(x => x.DisplayName)) { BuildFieldRow(html, member); } html.End() // table .EndSection(); } if(type.Properties.Any()) { html.StartSection(2, "properties", "Properties") .Start("table") .Start("tr").Elem("th", "Visibility").Elem("th", "Description").End(); foreach(var member in type.Properties.OrderBy(x => x.DisplayName)) { BuildPropertyRow(html, member); } html.End() // table .EndSection(); } if(type.Methods.Any()) { html.StartSection(2, "methods", "Methods") .Start("table") .Start("tr").Elem("th", "Visibility").Elem("th", "Description").End(); foreach(var member in type.Methods.OrderBy(x => x.DisplayName)) { BuildMethodRow(html, member); } html.End() // table .EndSection(); } if(type.Events.Any()) { html.StartSection(2, "events", "Events") .Start("table") .Start("tr").Elem("th", "Visibility").Elem("th", "Description").End(); foreach(var member in type.Events.OrderBy(x => x.DisplayName)) { BuildEventRow(html, member); } html.End() // table .EndSection(); } html.EndSection(); //members }
private void BuildInheritanceChain(XDoc html, ReflectedTypeInfo type) { html.StartNameValueBlock("inheritance", "Type Hierarchy"); var chain = GetParents(type.BaseType).ToList(); foreach(var link in chain) { html.Start("ul") .Start("li"); BuildParameterMarkup(html, link); html.End(); // li } html.Start("ul") .Start("li").Elem("b", type.DisplayName).End(); var subclasses = (from t in _types where t.BaseType != null && !t.BaseType.IsGenericParameter && t.BaseType.Type == type select t).ToList(); if(subclasses.Any()) { html.Start("ul"); foreach(var subclass in subclasses) { html.Start("li"); if(IsTypeInDocumentation(subclass)) { html.Link(subclass.UriPath, subclass.DisplayName); } else { html.Value(subclass.DisplayName); } html.End(); // li } html.End(); // subclass ul } html.End(); // type ul for(var i = 0; i < chain.Count; i++) { html.End(); } html.EndNameValue(); }
protected bool IsTypeInDocumentation(ReflectedTypeInfo x) { if(_assemblies.ContainsKey(x.Assembly)) { if(!_namespaces.Any()) { return true; } foreach(string ns in _namespaces) { if(x.Namespace.StartsWith(ns)) { return true; } } } return false; }
private void BuildInterfaceBlock(XDoc html, ReflectedTypeInfo type) { if(type.Interfaces.Any()) { html.StartNameValueBlock("implements", "Implements") .Start("ul"); foreach(var interfaceParameter in type.Interfaces) { html.Start("li"); BuildParameterMarkup(html, interfaceParameter); html.End(); } html.End() // ul .EndNameValue(); } if(type.Kind == TypeKind.Interface) { var implementers = (from t in _types where t.Interfaces.Where(x => x.Type == type).Any() select t).ToList(); if(implementers.Any()) { html.StartNameValueBlock("implementors", "Implementors") .Start("ul"); foreach(var implementor in implementers) { html.Start("li"); if(IsTypeInDocumentation(implementor)) { html.Link(implementor.UriPath, implementor.DisplayName); } else { html.Value(implementor.DisplayName); } html.End(); } html.End() // ul .EndNameValue(); } } }