I have discovered that Cecil behaves differently when importing a type from
System.Reflection that is in the global (or better: in no) namespace vs.
reading it from an assembly.

In short, since System.Reflection reports null for the Namespace property
of a type in the global namespace, an imported TypeReference will have a
null namespace property. When reading the same type form an Assembly
definition, the namespace property is initialized to an empty string. This
is reinforced by the constructor of TypeReference:

protected TypeReference (string @namespace, string name)
: base (name)
{
this.@namespace = @namespace ?? string.Empty;
this.token = new MetadataToken (TokenType.TypeRef, 0);
}

However, such a guard is effectively disabled for importing a type into the
module via MetadataImporter (problematic line bold):

public TypeReference ImportType (Type type, IGenericContext context,
ImportGenericKind import_kind)
{
if (IsTypeSpecification (type) || ImportOpenGenericType (type, import_kind))
return ImportTypeSpecification (type, context);

var reference = new TypeReference (
string.Empty,
type.Name,
module,
ImportScope (type.Assembly),
type.IsValueType);

reference.etype = ImportElementType (type);

if (IsNestedType (type))
reference.DeclaringType = ImportType (type.DeclaringType, context,
import_kind);
else
* reference.Namespace = type.Namespace;*

if (type.IsGenericType)
ImportGenericParameters (reference, type.GetGenericArguments ());

return reference;
}

I don't know what the "correct" convention is, but I am pretty sure there
is a reason Cecil chose to prefer empty strings. The Lidin Book has to
offer this:

Namespace (offset in the #Strings stream). The namespace of the type, part
> of the full
> name to the left of the rightmost dot. Class Odd.or.Even from Chapter 1
> had Namespace
> Odd.or. The Namespace entry can be empty, if the full name of the class
> does not contain
> dots. The namespace and the name constitute the full name of the type.


If it is decided we should prefer empty namespaces, ImportType() would need
to be fixed, or even better, we make the not-null string a protected
invariant of TypeReference.

What's your opinion?

Regards,
Johannes

-- 
--
mono-cecil

Reply via email to