mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
512 lines
22 KiB
512 lines
22 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using SRM = System.Reflection.Metadata; |
|
using ICSharpCode.Decompiler.TypeSystem.Implementation; |
|
using ICSharpCode.Decompiler.Util; |
|
|
|
using static ICSharpCode.Decompiler.Metadata.MetadataExtensions; |
|
using System.Diagnostics; |
|
|
|
namespace ICSharpCode.Decompiler.TypeSystem |
|
{ |
|
/// <summary> |
|
/// Manages the NRefactory type system for the decompiler. |
|
/// </summary> |
|
/// <remarks> |
|
/// This class is thread-safe. |
|
/// </remarks> |
|
public class DecompilerTypeSystem : IDecompilerTypeSystem |
|
{ |
|
readonly Metadata.PEFile moduleDefinition; |
|
readonly ICompilation compilation; |
|
readonly ITypeResolveContext context; |
|
|
|
/// <summary> |
|
/// CecilLoader used for converting cecil type references to ITypeReference. |
|
/// May only be accessed within lock(typeReferenceCecilLoader). |
|
/// </summary> |
|
readonly MetadataLoader typeReferenceCecilLoader = new MetadataLoader(); |
|
|
|
/// <summary> |
|
/// Dictionary for NRefactory->Cecil lookup. |
|
/// May only be accessed within lock(entityDict) |
|
/// </summary> |
|
Dictionary<IUnresolvedEntity, SRM.EntityHandle> entityDict = new Dictionary<IUnresolvedEntity, SRM.EntityHandle>(); |
|
|
|
Dictionary<SRM.EntityHandle, IField> fieldLookupCache = new Dictionary<SRM.EntityHandle, IField>(); |
|
Dictionary<SRM.EntityHandle, IProperty> propertyLookupCache = new Dictionary<SRM.EntityHandle, IProperty>(); |
|
Dictionary<SRM.EntityHandle, IMethod> methodLookupCache = new Dictionary<SRM.EntityHandle, IMethod>(); |
|
Dictionary<SRM.EntityHandle, IEvent> eventLookupCache = new Dictionary<SRM.EntityHandle, IEvent>(); |
|
|
|
public DecompilerTypeSystem(Metadata.PEFile moduleDefinition) |
|
{ |
|
if (moduleDefinition == null) |
|
throw new ArgumentNullException(nameof(moduleDefinition)); |
|
this.moduleDefinition = moduleDefinition; |
|
MetadataLoader cecilLoader = new MetadataLoader { IncludeInternalMembers = true, LazyLoad = true, OnEntityLoaded = StoreMemberReference, ShortenInterfaceImplNames = false }; |
|
typeReferenceCecilLoader.SetCurrentModule(moduleDefinition); |
|
IUnresolvedAssembly mainAssembly = cecilLoader.LoadModule(moduleDefinition); |
|
// Load referenced assemblies and type-forwarder references. |
|
// This is necessary to make .NET Core/PCL binaries work better. |
|
var referencedAssemblies = new List<IUnresolvedAssembly>(); |
|
var assemblyReferenceQueue = new Queue<Metadata.AssemblyReference>(moduleDefinition.AssemblyReferences); |
|
var processedAssemblyReferences = new HashSet<Metadata.AssemblyReference>(KeyComparer.Create((Metadata.AssemblyReference reference) => reference.FullName)); |
|
while (assemblyReferenceQueue.Count > 0) { |
|
var asmRef = assemblyReferenceQueue.Dequeue(); |
|
if (!processedAssemblyReferences.Add(asmRef)) |
|
continue; |
|
var asm = moduleDefinition.AssemblyResolver.Resolve(asmRef); |
|
if (asm != null) { |
|
referencedAssemblies.Add(cecilLoader.LoadModule(asm)); |
|
var metadata = asm.GetMetadataReader(); |
|
foreach (var h in metadata.ExportedTypes) { |
|
var forwarder = metadata.GetExportedType(h); |
|
if (!forwarder.IsForwarder || forwarder.Implementation.Kind != SRM.HandleKind.AssemblyReference) continue; |
|
assemblyReferenceQueue.Enqueue(new Metadata.AssemblyReference(asm, (SRM.AssemblyReferenceHandle)forwarder.Implementation)); |
|
} |
|
} |
|
} |
|
compilation = new SimpleCompilation(mainAssembly, referencedAssemblies); |
|
// Primitive types are necessary to avoid assertions in ILReader. |
|
// Fallback to MinimalCorlib to provide the primitive types. |
|
if (compilation.FindType(KnownTypeCode.Void).Kind == TypeKind.Unknown || compilation.FindType(KnownTypeCode.Int32).Kind == TypeKind.Unknown) { |
|
referencedAssemblies.Add(MinimalCorlib.Instance); |
|
compilation = new SimpleCompilation(mainAssembly, referencedAssemblies); |
|
} |
|
context = new SimpleTypeResolveContext(compilation.MainAssembly); |
|
} |
|
|
|
public ICompilation Compilation { |
|
get { return compilation; } |
|
} |
|
|
|
public IAssembly MainAssembly { |
|
get { return compilation.MainAssembly; } |
|
} |
|
|
|
public Metadata.PEFile ModuleDefinition { |
|
get { return moduleDefinition; } |
|
} |
|
|
|
public SRM.MetadataReader GetMetadata() => moduleDefinition.GetMetadataReader(); |
|
|
|
void StoreMemberReference(IUnresolvedEntity entity, SRM.EntityHandle mr) |
|
{ |
|
// This is a callback from the type system, which is multi-threaded and may be accessed externally |
|
lock (entityDict) |
|
entityDict[entity] = mr; |
|
} |
|
|
|
public IType ResolveFromSignature(ITypeReference typeReference) |
|
{ |
|
return typeReference.Resolve(context); |
|
} |
|
|
|
public IMember ResolveAsMember(SRM.EntityHandle memberReference) |
|
{ |
|
switch (memberReference.Kind) { |
|
case SRM.HandleKind.FieldDefinition: |
|
return ResolveAsField(memberReference); |
|
case SRM.HandleKind.MethodDefinition: |
|
return ResolveAsMethod(memberReference); |
|
case SRM.HandleKind.MemberReference: |
|
var mr = moduleDefinition.GetMetadataReader().GetMemberReference((SRM.MemberReferenceHandle)memberReference); |
|
switch (mr.GetKind()) { |
|
case SRM.MemberReferenceKind.Method: |
|
return ResolveAsMethod(memberReference); |
|
case SRM.MemberReferenceKind.Field: |
|
return ResolveAsField(memberReference); |
|
} |
|
throw new NotSupportedException(); |
|
case SRM.HandleKind.EventDefinition: |
|
return ResolveAsEvent(memberReference); |
|
case SRM.HandleKind.PropertyDefinition: |
|
return ResolveAsProperty(memberReference); |
|
case SRM.HandleKind.MethodSpecification: |
|
return ResolveAsMethod(memberReference); |
|
default: |
|
throw new NotSupportedException(); |
|
} |
|
} |
|
|
|
#region Resolve Type |
|
public IType ResolveAsType(SRM.EntityHandle typeReference) |
|
{ |
|
if (typeReference.IsNil) |
|
return SpecialType.UnknownType; |
|
ITypeReference typeRef; |
|
lock (typeReferenceCecilLoader) |
|
typeRef = typeReferenceCecilLoader.ReadTypeReference(typeReference); |
|
return typeRef.Resolve(context); |
|
} |
|
#endregion |
|
|
|
#region Resolve Field |
|
public IField ResolveAsField(SRM.EntityHandle fieldReference) |
|
{ |
|
if (fieldReference.IsNil) |
|
throw new ArgumentNullException(nameof(fieldReference)); |
|
if (fieldReference.Kind != SRM.HandleKind.FieldDefinition && fieldReference.Kind != SRM.HandleKind.MemberReference) |
|
throw new ArgumentException("HandleKind must be either FieldDefinition or MemberReference", nameof(fieldReference)); |
|
lock (fieldLookupCache) { |
|
IField field; |
|
if (!fieldLookupCache.TryGetValue(fieldReference, out field)) { |
|
var metadata = moduleDefinition.GetMetadataReader(); |
|
IType declaringType; |
|
ITypeReference returnType; |
|
switch (fieldReference.Kind) { |
|
case SRM.HandleKind.FieldDefinition: |
|
var fieldDef = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)fieldReference); |
|
declaringType = ResolveAsType(fieldDef.GetDeclaringType()); |
|
returnType = DynamicAwareTypeReference.Create(fieldDef.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default), fieldDef.GetCustomAttributes(), metadata); |
|
var declaringTypeDefinition = declaringType.GetDefinition(); |
|
if (declaringTypeDefinition == null) |
|
field = CreateFakeField(declaringType, metadata.GetString(fieldDef.Name), returnType); |
|
else { |
|
field = declaringTypeDefinition.GetFields(f => f.MetadataToken == fieldReference, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault() |
|
?? CreateFakeField(declaringType, metadata.GetString(fieldDef.Name), returnType); |
|
} |
|
break; |
|
case SRM.HandleKind.MemberReference: |
|
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)fieldReference); |
|
Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Field); |
|
declaringType = ResolveAsType(memberRef.Parent); |
|
field = FindNonGenericField(metadata, memberRef, declaringType); |
|
break; |
|
default: |
|
throw new NotSupportedException(); |
|
} |
|
if (declaringType.TypeArguments.Count > 0) { |
|
field = (IField)field.Specialize(new TypeParameterSubstitution(declaringType.TypeArguments, null)); |
|
} |
|
fieldLookupCache.Add(fieldReference, field); |
|
} |
|
return field; |
|
} |
|
} |
|
|
|
IField FindNonGenericField(SRM.MetadataReader metadata, SRM.MemberReference memberRef, IType declaringType) |
|
{ |
|
string name = metadata.GetString(memberRef.Name); |
|
ITypeDefinition typeDef = declaringType.GetDefinition(); |
|
ITypeReference returnType = memberRef.DecodeFieldSignature(TypeReferenceSignatureDecoder.Instance, default); |
|
|
|
if (typeDef == null) |
|
return CreateFakeField(declaringType, name, returnType); |
|
foreach (IField field in typeDef.Fields) |
|
if (field.Name == name) |
|
return field; |
|
return CreateFakeField(declaringType, name, returnType); |
|
} |
|
|
|
IField CreateFakeField(IType declaringType, string name, ITypeReference returnType) |
|
{ |
|
var f = new DefaultUnresolvedField(); |
|
f.Name = name; |
|
f.ReturnType = returnType; |
|
return new ResolvedFakeField(f, context.WithCurrentTypeDefinition(declaringType.GetDefinition()), declaringType); |
|
} |
|
|
|
class ResolvedFakeField : DefaultResolvedField |
|
{ |
|
readonly IType declaringType; |
|
|
|
public ResolvedFakeField(DefaultUnresolvedField unresolved, ITypeResolveContext parentContext, IType declaringType) |
|
: base(unresolved, parentContext) |
|
{ |
|
this.declaringType = declaringType; |
|
} |
|
|
|
public override IType DeclaringType |
|
{ |
|
get { return declaringType; } |
|
} |
|
} |
|
#endregion |
|
|
|
#region Resolve Method |
|
public IMethod ResolveAsMethod(SRM.EntityHandle methodReference) |
|
{ |
|
if (methodReference.IsNil) |
|
throw new ArgumentNullException(nameof(methodReference)); |
|
if (methodReference.Kind != SRM.HandleKind.MethodDefinition && methodReference.Kind != SRM.HandleKind.MemberReference && methodReference.Kind != SRM.HandleKind.MethodSpecification) |
|
throw new ArgumentException("HandleKind must be either a MethodDefinition, MemberReference or MethodSpecification", nameof(methodReference)); |
|
lock (methodLookupCache) { |
|
IMethod method; |
|
IType declaringType; |
|
IReadOnlyList<IType> classTypeArguments = null; |
|
IReadOnlyList<IType> methodTypeArguments = null; |
|
SRM.MethodSignature<ITypeReference>? signature = null; |
|
if (!methodLookupCache.TryGetValue(methodReference, out method)) { |
|
var metadata = moduleDefinition.GetMetadataReader(); |
|
switch (methodReference.Kind) { |
|
case SRM.HandleKind.MethodDefinition: |
|
var methodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)methodReference); |
|
signature = methodDef.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default); |
|
method = FindNonGenericMethod(metadata, methodReference, out declaringType); |
|
break; |
|
case SRM.HandleKind.MemberReference: |
|
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)methodReference); |
|
Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Method); |
|
signature = memberRef.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default); |
|
var elementMethod = methodReference; |
|
if (memberRef.Parent.Kind == SRM.HandleKind.MethodDefinition) { |
|
elementMethod = (SRM.MethodDefinitionHandle)memberRef.Parent; |
|
} |
|
method = FindNonGenericMethod(metadata, elementMethod, out declaringType); |
|
break; |
|
case SRM.HandleKind.MethodSpecification: |
|
var methodSpec = metadata.GetMethodSpecification((SRM.MethodSpecificationHandle)methodReference); |
|
method = FindNonGenericMethod(metadata, methodSpec.Method, out declaringType); |
|
var typeArguments = methodSpec.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default); |
|
if (typeArguments.Length > 0) { |
|
methodTypeArguments = typeArguments.SelectArray(arg => arg.Resolve(context)); |
|
} |
|
break; |
|
default: |
|
throw new NotSupportedException(); |
|
} |
|
if (signature?.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) { |
|
method = new VarArgInstanceMethod(method, signature.Value.ParameterTypes.Skip(signature.Value.RequiredParameterCount).Select(p => p.Resolve(context))); |
|
} |
|
if (declaringType.TypeArguments.Count > 0) { |
|
classTypeArguments = declaringType.TypeArguments.ToList(); |
|
} |
|
if (classTypeArguments != null || methodTypeArguments != null) { |
|
method = method.Specialize(new TypeParameterSubstitution(classTypeArguments, methodTypeArguments)); |
|
} |
|
|
|
methodLookupCache.Add(methodReference, method); |
|
} |
|
return method; |
|
} |
|
} |
|
|
|
IMethod FindNonGenericMethod(SRM.MetadataReader metadata, SRM.EntityHandle methodReference, out IType declaringType) |
|
{ |
|
ITypeDefinition declaringTypeDefinition; |
|
string name; |
|
switch (methodReference.Kind) { |
|
case SRM.HandleKind.MethodDefinition: |
|
var methodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)methodReference); |
|
declaringType = ResolveAsType(methodDef.GetDeclaringType()); |
|
declaringTypeDefinition = declaringType.GetDefinition(); |
|
if (declaringTypeDefinition == null) { |
|
return CreateFakeMethod(declaringType, metadata.GetString(methodDef.Name), methodDef.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default)); |
|
} |
|
name = metadata.GetString(methodDef.Name); |
|
IMethod method; |
|
if (name == ".ctor") { |
|
method = declaringTypeDefinition.GetConstructors(m => m.MetadataToken == methodReference, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); |
|
} else if (name == ".cctor") { |
|
method = declaringTypeDefinition.Methods.FirstOrDefault(m => m.MetadataToken == methodReference); |
|
} else { |
|
method = declaringTypeDefinition.GetMethods(m => m.MetadataToken == methodReference, GetMemberOptions.IgnoreInheritedMembers) |
|
.Concat(declaringTypeDefinition.GetAccessors(m => m.MetadataToken == methodReference, GetMemberOptions.IgnoreInheritedMembers)).FirstOrDefault(); |
|
} |
|
return method ?? CreateFakeMethod(declaringType, metadata.GetString(methodDef.Name), methodDef.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default)); |
|
case SRM.HandleKind.MemberReference: |
|
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)methodReference); |
|
Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Method); |
|
// TODO : Support other handles |
|
switch (memberRef.Parent.Kind) { |
|
case SRM.HandleKind.MethodDefinition: |
|
FindNonGenericMethod(metadata, memberRef.Parent, out declaringType); |
|
break; |
|
default: |
|
declaringType = ResolveAsType(memberRef.Parent); |
|
break; |
|
} |
|
declaringTypeDefinition = declaringType.GetDefinition(); |
|
var signature = memberRef.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default); |
|
if (declaringTypeDefinition == null) { |
|
return CreateFakeMethod(declaringType, metadata.GetString(memberRef.Name), signature); |
|
} |
|
IEnumerable<IMethod> methods; |
|
name = metadata.GetString(memberRef.Name); |
|
if (name == ".ctor") { |
|
methods = declaringTypeDefinition.GetConstructors(); |
|
} else if (name == ".cctor") { |
|
return declaringTypeDefinition.Methods.FirstOrDefault(m => m.IsConstructor && m.IsStatic); |
|
} else { |
|
methods = declaringTypeDefinition.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers) |
|
.Concat(declaringTypeDefinition.GetAccessors(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers)); |
|
} |
|
IType[] parameterTypes; |
|
if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) { |
|
parameterTypes = signature.ParameterTypes |
|
.Take(signature.RequiredParameterCount) |
|
.Select(p => p.Resolve(context)) |
|
.Concat(new[] { SpecialType.ArgList }) |
|
.ToArray(); |
|
} else { |
|
parameterTypes = signature.ParameterTypes.SelectArray(p => p.Resolve(context)); |
|
} |
|
var returnType = signature.ReturnType.Resolve(context); |
|
foreach (var m in methods) { |
|
if (m.TypeParameters.Count != signature.GenericParameterCount) |
|
continue; |
|
if (!CompareSignatures(m.Parameters, parameterTypes) || !CompareTypes(m.ReturnType, returnType)) |
|
continue; |
|
return m; |
|
} |
|
return CreateFakeMethod(declaringType, metadata.GetString(memberRef.Name), signature); |
|
default: |
|
throw new NotSupportedException(); |
|
} |
|
} |
|
|
|
static bool CompareTypes(IType a, IType b) |
|
{ |
|
IType type1 = DummyTypeParameter.NormalizeAllTypeParameters(a); |
|
IType type2 = DummyTypeParameter.NormalizeAllTypeParameters(b); |
|
return type1.Equals(type2); |
|
} |
|
|
|
static bool IsVarArgMethod(IMethod method) |
|
{ |
|
return method.Parameters.Count > 0 && method.Parameters[method.Parameters.Count - 1].Type.Kind == TypeKind.ArgList; |
|
} |
|
|
|
static bool CompareSignatures(IReadOnlyList<IParameter> parameters, IType[] parameterTypes) |
|
{ |
|
if (parameterTypes.Length != parameters.Count) |
|
return false; |
|
for (int i = 0; i < parameterTypes.Length; i++) { |
|
if (!CompareTypes(parameterTypes[i], parameters[i].Type)) |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
/// <summary> |
|
/// Create a dummy IMethod from the specified MethodReference |
|
/// </summary> |
|
IMethod CreateFakeMethod(IType declaringType, string name, SRM.MethodSignature<ITypeReference> signature) |
|
{ |
|
var m = new DefaultUnresolvedMethod(); |
|
if (name == ".ctor" || name == ".cctor") |
|
m.SymbolKind = SymbolKind.Constructor; |
|
m.Name = name; |
|
m.MetadataToken = default(SRM.MethodDefinitionHandle); |
|
m.ReturnType = signature.ReturnType; |
|
m.IsStatic = !signature.Header.IsInstance; |
|
|
|
lock (typeReferenceCecilLoader) { |
|
var metadata = moduleDefinition.GetMetadataReader(); |
|
for (int i = 0; i < signature.GenericParameterCount; i++) { |
|
m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, i, "")); |
|
} |
|
for (int i = 0; i < signature.ParameterTypes.Length; i++) { |
|
m.Parameters.Add(new DefaultUnresolvedParameter(signature.ParameterTypes[i], "")); |
|
} |
|
} |
|
return new ResolvedFakeMethod(m, context.WithCurrentTypeDefinition(declaringType.GetDefinition()), declaringType); |
|
} |
|
|
|
class ResolvedFakeMethod : DefaultResolvedMethod |
|
{ |
|
readonly IType declaringType; |
|
|
|
public ResolvedFakeMethod(DefaultUnresolvedMethod unresolved, ITypeResolveContext parentContext, IType declaringType) |
|
: base(unresolved, parentContext) |
|
{ |
|
this.declaringType = declaringType; |
|
} |
|
|
|
public override IType DeclaringType |
|
{ |
|
get { return declaringType; } |
|
} |
|
} |
|
#endregion |
|
|
|
#region Resolve Property |
|
public IProperty ResolveAsProperty(SRM.EntityHandle propertyReference) |
|
{ |
|
if (propertyReference.IsNil) |
|
throw new ArgumentNullException(nameof(propertyReference)); |
|
if (propertyReference.Kind != SRM.HandleKind.PropertyDefinition) |
|
throw new ArgumentException("HandleKind must be PropertyDefinition", nameof(propertyReference)); |
|
lock (propertyLookupCache) { |
|
IProperty property; |
|
if (!propertyLookupCache.TryGetValue(propertyReference, out property)) { |
|
var metadata = moduleDefinition.GetMetadataReader(); |
|
property = FindNonGenericProperty(metadata, (SRM.PropertyDefinitionHandle)propertyReference); |
|
/*if (propertyReference.DeclaringType.IsGenericInstance) { |
|
var git = (GenericInstanceType)propertyReference.DeclaringType; |
|
var typeArguments = git.GenericArguments.SelectArray(Resolve); |
|
property = (IProperty)property.Specialize(new TypeParameterSubstitution(typeArguments, null)); |
|
}*/ |
|
propertyLookupCache.Add(propertyReference, property); |
|
} |
|
return property; |
|
} |
|
} |
|
|
|
IProperty FindNonGenericProperty(SRM.MetadataReader metadata, SRM.PropertyDefinitionHandle handle) |
|
{ |
|
var propertyDefinition = metadata.GetPropertyDefinition(handle); |
|
var declaringType = metadata.GetMethodDefinition(propertyDefinition.GetAccessors().GetAny()).GetDeclaringType(); |
|
ITypeDefinition typeDef = ResolveAsType(declaringType).GetDefinition(); |
|
if (typeDef == null) |
|
return null; |
|
foreach (IProperty property in typeDef.Properties) { |
|
if (property.MetadataToken == handle) |
|
return property; |
|
} |
|
return null; |
|
} |
|
#endregion |
|
|
|
#region Resolve Event |
|
public IEvent ResolveAsEvent(SRM.EntityHandle eventReference) |
|
{ |
|
if (eventReference.IsNil) |
|
throw new ArgumentNullException(nameof(eventReference)); |
|
if (eventReference.Kind != SRM.HandleKind.EventDefinition) |
|
throw new ArgumentException("HandleKind must be EventDefinition", nameof(eventReference)); |
|
lock (eventLookupCache) { |
|
IEvent ev; |
|
if (!eventLookupCache.TryGetValue(eventReference, out ev)) { |
|
var metadata = moduleDefinition.GetMetadataReader(); |
|
ev = FindNonGenericEvent(metadata, (SRM.EventDefinitionHandle)eventReference); |
|
/*if (eventReference.DeclaringType.IsGenericInstance) { |
|
var git = (GenericInstanceType)eventReference.DeclaringType; |
|
var typeArguments = git.GenericArguments.SelectArray(Resolve); |
|
ev = (IEvent)ev.Specialize(new TypeParameterSubstitution(typeArguments, null)); |
|
}*/ |
|
eventLookupCache.Add(eventReference, ev); |
|
} |
|
return ev; |
|
} |
|
} |
|
|
|
IEvent FindNonGenericEvent(SRM.MetadataReader metadata, SRM.EventDefinitionHandle handle) |
|
{ |
|
var eventDefinition = metadata.GetEventDefinition(handle); |
|
var declaringType = metadata.GetMethodDefinition(eventDefinition.GetAccessors().GetAny()).GetDeclaringType(); |
|
ITypeDefinition typeDef = ResolveAsType(declaringType).GetDefinition(); |
|
if (typeDef == null) |
|
return null; |
|
var returnType = ResolveAsType(eventDefinition.Type); |
|
string name = metadata.GetString(eventDefinition.Name); |
|
foreach (IEvent ev in typeDef.Events) { |
|
if (ev.MetadataToken == handle) |
|
return ev; |
|
} |
|
return null; |
|
} |
|
#endregion |
|
|
|
public IDecompilerTypeSystem GetSpecializingTypeSystem(TypeParameterSubstitution substitution) |
|
{ |
|
if (substitution.Equals(TypeParameterSubstitution.Identity)) { |
|
return this; |
|
} else { |
|
return new SpecializingDecompilerTypeSystem(this, substitution); |
|
} |
|
} |
|
} |
|
}
|
|
|