diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs
index 7a489d07e..397b82030 100644
--- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs
+++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs
@@ -128,6 +128,7 @@ namespace ICSharpCode.Decompiler.Ast
ConvertCustomAttributes(astCompileUnit, assemblyDefinition, "assembly");
ConvertSecurityAttributes(astCompileUnit, assemblyDefinition, "assembly");
ConvertCustomAttributes(astCompileUnit, assemblyDefinition.MainModule, "module");
+ AddTypeForwarderAttributes(astCompileUnit, assemblyDefinition.MainModule, "assembly");
if (!onlyAssemblyLevel) {
foreach (TypeDefinition typeDef in assemblyDefinition.MainModule.Types) {
@@ -142,6 +143,30 @@ namespace ICSharpCode.Decompiler.Ast
}
}
+ void AddTypeForwarderAttributes(CompilationUnit astCompileUnit, ModuleDefinition module, string target)
+ {
+ if (!module.HasExportedTypes)
+ return;
+ foreach (ExportedType type in module.ExportedTypes) {
+ if (type.IsForwarder) {
+ var forwardedType = CreateTypeOfExpression(new TypeReference(type.Namespace, type.Name, module, type.Scope));
+ astCompileUnit.AddChild(
+ new AttributeSection {
+ AttributeTarget = target,
+ Attributes = {
+ new NRefactory.CSharp.Attribute {
+ Type = new SimpleType("TypeForwardedTo")
+ .WithAnnotation(new TypeReference(
+ "System.Runtime.CompilerServices", "TypeForwardedToAttribute",
+ module, module.TypeSystem.Corlib)),
+ Arguments = { forwardedType }
+ }
+ }
+ }, AttributedNode.AttributeRole);
+ }
+ }
+ }
+
NamespaceDeclaration GetCodeNamespace(string name)
{
if (string.IsNullOrEmpty(name)) {
@@ -306,6 +331,45 @@ namespace ICSharpCode.Decompiler.Ast
return name;
}
+ #region Create TypeOf Expression
+ ///
+ /// Creates a typeof-expression for the specified type.
+ ///
+ public static TypeOfExpression CreateTypeOfExpression(TypeReference type)
+ {
+ return new TypeOfExpression(AddEmptyTypeArgumentsForUnboundGenerics(ConvertType(type)));
+ }
+
+ static AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type)
+ {
+ TypeReference typeRef = type.Annotation();
+ if (typeRef == null)
+ return type;
+ TypeDefinition typeDef = typeRef.Resolve(); // need to resolve to figure out the number of type parameters
+ if (typeDef == null || !typeDef.HasGenericParameters)
+ return type;
+ SimpleType sType = type as SimpleType;
+ MemberType mType = type as MemberType;
+ if (sType != null) {
+ while (typeDef.GenericParameters.Count > sType.TypeArguments.Count) {
+ sType.TypeArguments.Add(new SimpleType(""));
+ }
+ }
+
+ if (mType != null) {
+ AddEmptyTypeArgumentsForUnboundGenerics(mType.Target);
+
+ int outerTypeParamCount = typeDef.DeclaringType == null ? 0 : typeDef.DeclaringType.GenericParameters.Count;
+
+ while (typeDef.GenericParameters.Count - outerTypeParamCount > mType.TypeArguments.Count) {
+ mType.TypeArguments.Add(new SimpleType(""));
+ }
+ }
+
+ return type;
+ }
+ #endregion
+
#region Convert Type Reference
///
/// Converts a type reference.
@@ -1378,9 +1442,7 @@ namespace ICSharpCode.Decompiler.Ast
if (type != null && type.IsEnum) {
return MakePrimitive(Convert.ToInt64(argument.Value), type);
} else if (argument.Value is TypeReference) {
- return new TypeOfExpression() {
- Type = ConvertType((TypeReference)argument.Value),
- };
+ return CreateTypeOfExpression((TypeReference)argument.Value);
} else {
return new PrimitiveExpression(argument.Value);
}
diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
index c8666b73a..b82101562 100644
--- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
+++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
@@ -601,7 +601,7 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.Ldstr: return new Ast.PrimitiveExpression(operand);
case ILCode.Ldtoken:
if (operand is Cecil.TypeReference) {
- return new Ast.TypeOfExpression { Type = AddEmptyTypeArgumentsForUnboundGenerics(operandAsTypeRef) }.Member("TypeHandle");
+ return AstBuilder.CreateTypeOfExpression((TypeReference)operand).Member("TypeHandle");
} else {
return InlineAssembly(byteCode, args);
}
@@ -749,35 +749,6 @@ namespace ICSharpCode.Decompiler.Ast
}
}
- AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type)
- {
- TypeReference typeRef = type.Annotation();
- if (typeRef == null)
- return type;
- TypeDefinition typeDef = typeRef.Resolve(); // need to resolve to figure out the number of type parameters
- if (typeDef == null || !typeDef.HasGenericParameters)
- return type;
- SimpleType sType = type as SimpleType;
- MemberType mType = type as MemberType;
- if (sType != null) {
- while (typeDef.GenericParameters.Count > sType.TypeArguments.Count) {
- sType.TypeArguments.Add(new SimpleType(""));
- }
- }
-
- if (mType != null) {
- AddEmptyTypeArgumentsForUnboundGenerics(mType.Target);
-
- int outerTypeParamCount = typeDef.DeclaringType == null ? 0 : typeDef.DeclaringType.GenericParameters.Count;
-
- while (typeDef.GenericParameters.Count - outerTypeParamCount > mType.TypeArguments.Count) {
- mType.TypeArguments.Add(new SimpleType(""));
- }
- }
-
- return type;
- }
-
static readonly AstNode objectInitializerPattern = new AssignmentExpression(
new MemberReferenceExpression {
Target = new InitializedObjectExpression()
diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
index be00da59a..f4f8dac8a 100644
--- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
+++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
@@ -1096,6 +1096,21 @@ namespace ICSharpCode.Decompiler.Disassembler
public void WriteModuleHeader(ModuleDefinition module)
{
+ if (module.HasExportedTypes) {
+ foreach (ExportedType exportedType in module.ExportedTypes) {
+ output.Write(".class extern ");
+ if (exportedType.IsForwarder)
+ output.Write("forwarder ");
+ output.Write(exportedType.DeclaringType != null ? exportedType.Name : exportedType.FullName);
+ OpenBlock(false);
+ if (exportedType.DeclaringType != null)
+ output.WriteLine(".class extern {0}", DisassemblerHelpers.Escape(exportedType.DeclaringType.FullName));
+ else
+ output.WriteLine(".assembly extern {0}", DisassemblerHelpers.Escape(exportedType.Scope.Name));
+ CloseBlock();
+ }
+ }
+
output.WriteLine(".module {0}", module.Name);
output.WriteLine("// MVID: {0}", module.Mvid.ToString("B").ToUpperInvariant());
// TODO: imagebase, file alignment, stackreserve, subsystem