void ReadFixedArg(StringBuilder sb, ByteReader br, Type type, bool arrayElement = false)
{
if (type.IsArray)
{
int length = br.ReadInt32();
if (length == -1 && compat == CompatLevel.None)
{
sb.Append("nullref");
}
else if (length == 0 && compat != CompatLevel.None)
{
throw new Managed.Reflection.BadImageFormatException();
}
else
{
Type elementType = type.GetElementType();
AppendCATypeName(sb, elementType, null);
sb.AppendFormat("[{0}](", length);
for (int i = 0; i < length; i++)
{
if (i != 0)
{
sb.Append(' ');
}
if (elementType == typeofSystemObject)
{
string typeName;
ReadFixedArg(sb, br, ReadFieldOrPropType(sb, br, out typeName), false);
}
else
{
ReadFixedArg(sb, br, elementType, true);
}
}
sb.Append(')');
}
}
else if (type.FullName == "System.Type" && type.Assembly.GetName().Name == "mscorlib")
{
if (!arrayElement)
{
AppendCATypeName(sb, type, null);
sb.Append('(');
}
string typeName;
var type1 = ReadType(br, out typeName);
if (type1 == null)
{
if (typeName == null)
{
sb.Append("nullref");
}
else
{
sb.Append("class ").Append(QuoteIdentifier(typeName, true));
}
}
else
{
AppendTypeName(sb, type1, typeName, compat != CompatLevel.None && IsNestedTypeWithNamespace(type1));
}
if (!arrayElement)
{
sb.Append(')');
}
}
else if (type.Assembly == mscorlib)
{
if (!arrayElement)
{
AppendCATypeName(sb, type, null);
sb.Append('(');
}
if (type == typeofSystemBoolean)
{
sb.Append(br.ReadByte() == 0 ? "false" : "true");
}
else if (type == typeofSystemByte)
{
sb.Append(br.ReadByte());
}
else if (type == typeofSystemSByte)
{
sb.Append(br.ReadSByte());
}
else if (type == typeofSystemChar)
{
sb.AppendFormat("0x{0:X4}", (int)br.ReadChar());
}
else if (type == typeofSystemInt16)
{
sb.Append(br.ReadInt16());
}
else if (type == typeofSystemUInt16)
{
sb.Append(br.ReadUInt16());
}
else if (type == typeofSystemInt32)
{
sb.Append(br.ReadInt32());
}
else if (type == typeofSystemUInt32)
{
sb.Append(br.ReadInt32());
}
else if (type == typeofSystemInt64)
{
sb.Append(br.ReadInt64());
}
else if (type == typeofSystemUInt64)
{
sb.Append(br.ReadInt64());
}
else if (type == typeofSystemSingle)
{
sb.Append(ToString(br.ReadSingle(), true));
}
else if (type == typeofSystemDouble)
{
sb.Append(ToString(br.ReadDouble(), true));
}
else if (type == typeofSystemString)
{
var str = br.ReadString();
if (str == null)
{
sb.Append("nullref");
}
else
{
if (compat != CompatLevel.None)
{
int pos = str.IndexOf((char)0);
if (pos != -1)
{
str = str.Substring(0, pos);
}
}
sb.Append(QuoteIdentifier(str, true));
}
}
else if (type == typeofSystemObject)
{
string typeName;
ReadFixedArg(sb, br, ReadFieldOrPropType(sb, br, out typeName));
}
else
{
throw new NotImplementedException(type.FullName);
}
if (!arrayElement)
{
sb.Append(')');
}
}
else if (type.__IsMissing || (compat != CompatLevel.None && typerefs.Contains(type)))
{
// ildasm actually tries to load the assembly, but we can't do that, so we cheat by having
// a list of 'known' enum types
if (type.Assembly.GetName().Name == "mscorlib")
{
switch (type.FullName)
{
case "System.AttributeTargets":
case "System.Runtime.ConstrainedExecution.Consistency":
case "System.Runtime.ConstrainedExecution.Cer":
case "System.Security.Permissions.SecurityAction":
case "System.Security.Permissions.SecurityPermissionFlag":
case "System.Runtime.Versioning.ResourceScope":
case "System.Runtime.InteropServices.CallingConvention":
case "System.Runtime.InteropServices.CharSet":
ReadFixedArg(sb, br, typeofSystemInt32);
return;
case "System.Security.SecurityRuleSet":
if (compat != CompatLevel.V20)
{
ReadFixedArg(sb, br, typeofSystemByte);
return;
}
break;
case "System.Diagnostics.Tracing.EventLevel":
case "System.Diagnostics.Tracing.EventTask":
case "System.Diagnostics.Tracing.EventOpcode":
if (compat != CompatLevel.V20 && compat != CompatLevel.V40)
{
ReadFixedArg(sb, br, typeofSystemInt32);
return;
}
break;
case "System.Type":
sb.Append("type(");
string typeName;
AppendTypeName(sb, ReadType(br, out typeName), typeName);
sb.Append(")");
return;
}
}
switch (br.Length)
{
case 1:
if (compat != CompatLevel.None)
{
// ildasm uses bool (???) as the underlying type in this case
sb.AppendFormat("bool({0})", br.ReadByte() == 0 ? "false" : "true");
}
else
{
// just guess that the enum has int8 as the underlying type
sb.AppendFormat("int8({0})", br.ReadSByte());
}
break;
case 2:
// just guess that the enum has int16 as the underlying type
sb.AppendFormat("int16({0})", br.ReadInt16());
break;
case 4:
// just guess that the enum has int32 as the underlying type
sb.AppendFormat("int32({0})", br.ReadInt32());
break;
case 8:
// just guess that the enum has int64 as the underlying type
sb.AppendFormat("int64({0})", br.ReadInt64());
break;
default:
throw new Managed.Reflection.BadImageFormatException();
}
}
else if (type.IsEnum)
{
ReadFixedArg(sb, br, type.GetEnumUnderlyingType(), arrayElement);
}
else
{
throw new NotImplementedException(type.FullName);
}
}