This project is read-only.

Retrieve xml-doc identifier for given code model element?

Aug 28, 2007 at 4:49 PM
Reflector can retrieve documentation for the members, types and other model elements. So, I guess, there is code somewhere inside which can generate xml ID like "M:Microsoft.Win32.Registry.SetValue(System.String,System.String,System.Object,Microsoft.Win32.RegistryValueKind)" for the given element. Is it available through the public API, and if not could you please publish it? Thanks.
Aug 29, 2007 at 8:01 AM
You can try using this class to do the conversion:

internal class DocumentationKey
{
	private string identifier = string.Empty;
	private string kind = null;
	private string resolutionScope = null;
	private string type = null;
	private string member = null;
	private string parameters = null;
 
	private DocumentationKey()
	{
	}
 
	public DocumentationKey(object target)
	{
		this.identifier = "invalid";
 
		ITypeDeclaration typeDeclaration = target as ITypeDeclaration;
		if (typeDeclaration != null)
		{
			this.kind = "T:";
			this.SetTypeDeclaration(typeDeclaration);
		}
 
		IFieldDeclaration fieldDeclaration = target as IFieldDeclaration;
		if (fieldDeclaration != null)
		{
			this.kind = "F:";
			this.SetTypeDeclaration((fieldDeclaration.DeclaringType as ITypeReference).Resolve());
			this.member = fieldDeclaration.Name;
		}
 
		IMethodDeclaration methodDeclaration = target as IMethodDeclaration;
		if (methodDeclaration != null)
		{
			this.kind = "M:";
			this.SetTypeDeclaration((methodDeclaration.DeclaringType as ITypeReference).Resolve());
			this.member = this.GetMethodName(methodDeclaration);
			this.parameters = this.GetParameterDeclarationList(methodDeclaration.Parameters, methodDeclaration.CallingConvention, methodDeclaration.ReturnType, methodDeclaration.Name);
		}
 
		IPropertyDeclaration propertyDeclaration = target as IPropertyDeclaration;
		if (propertyDeclaration != null)
		{
			this.kind = "P:";
			this.SetTypeDeclaration((propertyDeclaration.DeclaringType as ITypeReference).Resolve());
			this.member = propertyDeclaration.Name;
			this.parameters = this.GetParameterDeclarationList (propertyDeclaration.Parameters, MethodCallingConvention.Default, null, null);
		}
 
		IEventDeclaration eventDeclaration = target as IEventDeclaration;
		if (eventDeclaration != null)
		{
			this.kind = "E:";
			this.SetTypeDeclaration((eventDeclaration.DeclaringType as ITypeReference).Resolve());
			this.member = eventDeclaration.Name;
		}
	}
 
	public string Identifier
	{
		get
		{
			if (this.kind == "N:")
			{
				return this.kind + this.resolutionScope;
			}
 
			string scope = (this.resolutionScope.Length > 0) ? (this.resolutionScope + ".") : string.Empty;
 
			switch (this.kind)
			{
				case "T:":
					return this.kind + scope + this.type;
 
				case "E:":
				case "F:":
					return this.kind + scope + this.type + "." + this.member.Replace ('.', '#');
 
				case "M:":
				case "P:":
					return this.kind + scope + this.type + "." + this.member.Replace ('.', '#') + this.parameters.Replace ('&', '@');
			}
 
			return this.identifier;
		}
	}
 
	private void SetTypeDeclaration(ITypeReference value)
	{
		this.resolutionScope = GetResolutionScope(value);
		this.type = GetTypeName(value);
	}
 
	private string GetMethodName(IMethodDeclaration methodDeclaration)
	{
		if (methodDeclaration.GenericArguments.Count != 0)
		{
			return methodDeclaration.Name + "``" + methodDeclaration.GenericArguments.Count.ToString(CultureInfo.InvariantCulture);
		}
		
		return methodDeclaration.Name;	
	}
 
	private string GetParameterDeclarationList(IParameterDeclarationCollection parameters, MethodCallingConvention callingConvention, IMethodReturnType methodReturnType, string methodName)
	{
		if (parameters.Count > 0)
		{
			using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
			{
				writer.Write("(");
				for (int i = 0; i < parameters.Count; i++)
				{
					if (i != 0)
					{
						writer.Write(",");
					}
 
					IType parameterType = parameters[i].ParameterType;
					writer.Write(this.GetType(parameterType));
				}
 
				if (callingConvention == MethodCallingConvention.VariableArguments)
				{
					writer.Write(",");
				}
 
				writer.Write(")");
				
				if ((methodReturnType != null) && (methodName != null) && (methodName.Length > 0))
				{
					if ((methodName	== "op_Explicit") || (methodName == "op_Implicit"))
					{
						writer.Write("~");
						writer.Write(this.GetType(methodReturnType.Type));
					}
				}
			
				return writer.ToString();
			}
		}
 
		return string.Empty;
	}
 
	private string GetTypeDescription()
	{
		int index = this.type.IndexOf('`');
		if (index != -1)
		{
			int count = int.Parse(this.type.Substring(index + 1), CultureInfo.InvariantCulture);
 
			using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
			{
				writer.Write(this.type.Substring(0, index));
				writer.Write("<");
 
				for (int i = 0; i < count - 1; i++)
				{
					writer.Write(",");
				}
 
				writer.Write(">");
				return writer.ToString();
			}
		}
		
		return this.type;
	}
	
	private string GetMethodDescription()
	{
		int index = this.member.IndexOf("``");
		if (index != -1)
		{
			int count = int.Parse(this.member.Substring(index + 2), CultureInfo.InvariantCulture);
 
			using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
			{
				writer.Write(this.member.Substring(0, index));
				writer.Write("<");
 
				for (int i = 0; i < count - 1; i++)
				{
					writer.Write(",");
				}
 
				writer.Write(">");
				return writer.ToString();
			}
		}
		
		return this.member;
	}
 
	private string GetType(IType type)
	{
		ITypeReference typeReference = type as ITypeReference;
		if (typeReference != null)
		{
			string name = typeReference.Name;
			
			if (typeReference.GenericArguments.Count != 0)
			{
				name = name + "{";
				
				for (int i = 0; i < typeReference.GenericArguments.Count; i++)
				{
					if (i != 0)
					{
						name = name + ",";
					}
 
					name = name + this.GetType(typeReference.GenericArguments[i]);
				}
				
				name = name + "}";
			}
			
			string resolutionScope = GetResolutionScope(typeReference);
			if (resolutionScope.Length > 0)
			{
				return resolutionScope + "." + name;
			}
 
			return name;
		}
 
		IArrayType arrayType = type as IArrayType;
		if (arrayType != null)
		{
			using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
			{
				writer.Write(this.GetType (arrayType.ElementType));
				writer.Write("[");
 
				IArrayDimensionCollection dimensions = arrayType.Dimensions;
				for (int i = 0; i < dimensions.Count; i++)
				{
					if (i != 0)
					{
						writer.Write (",");
					}
 
					int lowerBound = dimensions[i].LowerBound;
					int upperBound = dimensions[i].UpperBound;
 
					if (lowerBound != -1)
					{
						writer.Write(lowerBound.ToString(CultureInfo.InvariantCulture));
					}
 
					if ((lowerBound != -1) || (upperBound != -1))
					{
						writer.Write(":");
					}
 
					if (upperBound != -1)
					{
						writer.Write(upperBound.ToString(CultureInfo.InvariantCulture));
					}
				}
 
				writer.Write ("]");
				return writer.ToString();
			}
		}
 
		IReferenceType referenceType = type as IReferenceType;
		if (referenceType != null)
		{
			return this.GetType(referenceType.ElementType) + "&";
		}
 
		IPointerType pointerType = type as IPointerType;
		if (pointerType != null)
		{
			return this.GetType(pointerType.ElementType) + "*";
		}
 
		IOptionalModifier optionalModifier = type as IOptionalModifier;
		if (optionalModifier != null)
		{
			return this.GetType(optionalModifier.ElementType);
		}
 
		IRequiredModifier requiredModifier = type as IRequiredModifier;
		if (requiredModifier != null)
		{
			return this.GetType(requiredModifier.ElementType);
		}
 
		IGenericParameter genericParameter = type as IGenericParameter;
		if (genericParameter != null)
		{
			return genericParameter.Name;
		}
 
		IGenericArgument genericArgument = type as IGenericArgument;
		if (genericArgument != null)
		{
			ITypeReference genericType = genericArgument.Owner as ITypeReference;
			if (genericType != null)
			{
				return "`" + genericArgument.Position.ToString(CultureInfo.InvariantCulture); 
			}
 
			IMethodReference genericMethod = genericArgument.Owner as IMethodReference;
			if (genericMethod != null)
			{
				return "``" + genericArgument.Position.ToString(CultureInfo.InvariantCulture);
			}				
		}
 
		return "?";
	}
 
	private static string GetTypeName(ITypeReference value)
	{
		int count = value.GenericArguments.Count;
 
		ITypeReference declaringType = value.Owner as ITypeReference;
		if (declaringType != null)
		{
			count -= declaringType.GenericArguments.Count;
		}
 
		if (count != 0)
		{
			return value.Name + "`" + count.ToString(CultureInfo.InvariantCulture);
		}
 
		return value.Name;
	}
 
	private static string GetResolutionScope(ITypeReference value)
	{
		ITypeReference declaringType = value.Owner as ITypeReference;
		if (declaringType != null)
		{
			string resolutionScope = GetResolutionScope(declaringType);
			if (resolutionScope.Length > 0)
			{
				resolutionScope += ".";
			}
 
			return resolutionScope + GetTypeName(declaringType);
		}
 
		return value.Namespace;
	}
}
Aug 29, 2007 at 10:24 AM
Thanks a lot, Lutz!

I still think this could be part of the public API, something like property of IDocumentationProvider.