/// <summary> /// Load additional documentation information from the assembly itself. /// </summary> public virtual void AddAssemblyInfo(FieldInfo fieldInfo) { if (fieldInfo.Attributes.IsConstant()) { Category = FieldCategory.Constant; } else if (fieldInfo.IsInitOnly) { Category = FieldCategory.ReadOnly; } else { Category = FieldCategory.Normal; } if (fieldInfo.IsPublic) { AccessModifier = AccessModifier.Public; } else if (fieldInfo.IsFamily) { AccessModifier = AccessModifier.Protected; } else if (fieldInfo.IsAssembly) { AccessModifier = AccessModifier.Internal; } else if (fieldInfo.IsFamilyOrAssembly) { AccessModifier = AccessModifier.InternalProtected; } else { AccessModifier = AccessModifier.Private; } if (fieldInfo.IsStatic) { IsStatic = true; } if (Category == FieldCategory.Constant) { try { ConstantValue = fieldInfo.GetRawConstantValue(); } catch (Exception) { //System.InvalidOperationException: Operation is not valid due to the current state of the object. } } TypeName = DotNetQualifiedTypeName.FromAssemblyInfo(fieldInfo.FieldType); }
/// <summary> /// Load additional documentation information from the assembly itself. /// </summary> public virtual void AddAssemblyInfo(PropertyInfo propertyInfo) { GetterMethod = DotNetPropertyMethod.FromAssemblyInfo(propertyInfo.GetGetMethod(true)); //true means also return non-public methods SetterMethod = DotNetPropertyMethod.FromAssemblyInfo(propertyInfo.GetSetMethod(true)); TypeName = DotNetQualifiedTypeName.FromAssemblyInfo(propertyInfo.PropertyType); Category = FieldCategory.Normal; if (HasGetterMethod && GetterMethod.IsAbstract && HasSetterMethod && SetterMethod.IsAbstract) { Category = FieldCategory.Abstract; } }
/// <summary> /// Returns true if signatures match. Looks at types only, not at names. /// </summary> public bool MatchesSignature(ParameterInfo parameterInfo) { if (TypeName is DotNetReferenceClassGeneric) { return((TypeName as DotNetReferenceClassGeneric).MatchesSignature(parameterInfo.ParameterType)); } else if (TypeName is DotNetReferenceMethodGeneric) { return((TypeName as DotNetReferenceMethodGeneric).MatchesSignature(parameterInfo.ParameterType)); } else { string otherName = DotNetQualifiedTypeName.FromAssemblyInfo(parameterInfo.ParameterType).FullName; return(FullTypeName == otherName); } }
/// <summary> /// Returns true if this method's parameter list matches the reflected ParameterInfo. /// </summary> public bool MatchesArguments(ParameterInfo[] otherParameters) { if (Parameters.Count != otherParameters.Length) { return(false); } for (int i = 0; i < Parameters.Count; i++) { string otherName = DotNetQualifiedTypeName.FromAssemblyInfo(otherParameters[i].ParameterType).FullName; if (Parameters[i].FullTypeName != otherName) { return(false); } } return(true); }
/// <summary> /// Parses a System.Reflection.AssemblyInfo full name. /// </summary> /// <list> /// <item>The escape character is backslash (\)</item> /// <item>Nested types are separated with '+' instead of '.'</item> /// <item>Class declaration of generic types are shown the same as .Net XML documentation: MyType`1 for one generic type</item> /// <item>When a generic type is defined: System.Collections.Generic.List`1[U], where U is the type alias from the class declaration</item> /// </list> /// <param name="type"></param> /// <param name="bubbleUpParameters">Optional. When reflection gives type information about a generic type nested inside a generic type, all the generic-type-arguments are listed in the inner-most type. This is for passing that information back up the chain of types.</param> public static DotNetQualifiedTypeName FromAssemblyInfo(Type type, List <DotNetQualifiedTypeName> bubbleUpParameters = null) { if (type == null) { return(new DotNetQualifiedTypeName()); } string typeName = type.FullName; if (String.IsNullOrEmpty(typeName)) { typeName = type.Name; //for generic types } typeName = typeName.Replace("@", "").Replace("&", ""); //out and ref modifiers do not differentiate method signatures typeName = typeName.ReplaceUnescapedCharacters('\\', '+', '.'); if (String.IsNullOrEmpty(typeName)) { typeName = ""; //todo: this should not be necessary, track down case in EarlyDocs } List <DotNetQualifiedTypeName> parameters = new List <DotNetQualifiedTypeName>(); int genericParameterCount = 0; if (!type.IsGenericParameter) { if (type.ContainsGenericParameters) //generic type, with parameters unspecified { if (bubbleUpParameters != null && bubbleUpParameters.Count > 0) //actually, this is a generic type with specific parameter types that has a nested generic type within it { parameters = new List <DotNetQualifiedTypeName>(bubbleUpParameters); } else { parameters = type.GetGenericArguments().Select(a => FromAssemblyInfo(a)).ToList(); } if (typeName.Contains("[")) { typeName = typeName.Substring(0, typeName.IndexOf("[")); } Int32.TryParse(typeName.Substring(typeName.LastIndexOf("`") + 1), out genericParameterCount); typeName = typeName.Substring(0, typeName.LastIndexOf("`")); } else if (type.GetGenericArguments().Length > 0) //generic type, with specific parameter types { //TODO is this all correct? what case where these commented out statements meant to handle? //int parameterPosition = 0; foreach (Type parameter in type.GetGenericArguments()) { parameters.Add(FromAssemblyInfo(parameter)); //parameters.Add(new DotNetReferenceClassGeneric(parameterPosition, parameter.Name)); //parameterPosition++; } typeName = typeName.Substring(0, typeName.IndexOf("[")); string numberString = typeName.Substring(typeName.LastIndexOf("`") + 1); Int32.TryParse(numberString, out genericParameterCount); typeName = typeName.Substring(0, typeName.LastIndexOf("`")); if (bubbleUpParameters != null) { if (parameters.Count > bubbleUpParameters.Count) { throw new Exception("Type has more generic-type-parameters than expected."); } int remainder = bubbleUpParameters.Count - parameters.Count; parameters = bubbleUpParameters.Skip(remainder).ToList(); bubbleUpParameters = bubbleUpParameters.Take(remainder).ToList(); } } } int divider = typeName.LastIndexOf('.'); string localName = typeName; string fullNamespaceString = null; if (divider != -1) { localName = typeName.Substring(divider + 1); fullNamespaceString = typeName.Substring(0, divider); } if (String.IsNullOrEmpty(fullNamespaceString)) { return(new DotNetQualifiedTypeName(localName, parameters)); } //so, if a generic type is nested inside another generic type, the Assembly info returns the full list of expected generic parameters to the innermost generic type //which means I need to pass them back up List <DotNetQualifiedTypeName> outerParameters = null; if (genericParameterCount < parameters.Count) { outerParameters = parameters.Take(parameters.Count - genericParameterCount).ToList(); parameters = parameters.Skip(outerParameters.Count).ToList(); } DotNetQualifiedTypeName fullNamespace = null; if (type.DeclaringType != null) { fullNamespace = DotNetQualifiedTypeName.FromAssemblyInfo(type.DeclaringType, outerParameters); } else { fullNamespace = DotNetQualifiedTypeName.FromAssemblyInfo(fullNamespaceString); } return(new DotNetQualifiedTypeName(localName, parameters, fullNamespace)); }
/// <summary> /// Load additional documentation information from the assembly itself. /// </summary> public void AddAssemblyInfo(EventInfo eventInfo) { TypeName = DotNetQualifiedTypeName.FromAssemblyInfo(eventInfo.EventHandlerType); }