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 IList<ReflectedParameterInfo> GetParameters(ParameterInfo[] parameters, ParameterBuilder builder) { var parameterList = new List<ReflectedParameterInfo>(); foreach(var parameter in parameters) { var param = builder.BuildParameter(parameter); parameterList.Add(param); } return parameterList; }
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; }