-
Notifications
You must be signed in to change notification settings - Fork 87
/
MemberRef.cs
149 lines (123 loc) · 5.22 KB
/
MemberRef.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright (c) Microsoft. All rights reserved.
namespace Microsoft.VisualStudio.Composition.Reflection
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
public abstract class MemberRef : IEquatable<MemberRef>
{
/// <summary>
/// The metadata token for this member if read from a persisted assembly.
/// We do not store metadata tokens for members in dynamic assemblies because they can change till the Type is closed.
/// </summary>
private readonly int? metadataToken;
/// <summary>
/// The <see cref="MemberInfo"/> that this value was instantiated with,
/// or cached later when a metadata token was resolved.
/// </summary>
private MemberInfo cachedMemberInfo;
/// <summary>
/// Initializes a new instance of the <see cref="MemberRef"/> class.
/// </summary>
protected MemberRef(TypeRef declaringType, int metadataToken, bool isStatic)
{
Requires.NotNull(declaringType, nameof(declaringType));
this.DeclaringType = declaringType;
this.metadataToken = metadataToken;
this.IsStatic = isStatic;
}
protected MemberRef(TypeRef declaringType, MemberInfo memberInfo)
{
Requires.NotNull(declaringType, nameof(declaringType));
Requires.NotNull(memberInfo, nameof(memberInfo));
this.DeclaringType = declaringType;
this.cachedMemberInfo = memberInfo;
this.IsStatic = memberInfo.IsStatic();
}
protected MemberRef(MemberInfo memberInfo, Resolver resolver)
: this(
TypeRef.Get(Requires.NotNull(memberInfo, nameof(memberInfo)).DeclaringType, resolver),
memberInfo)
{
}
public TypeRef DeclaringType { get; }
public AssemblyName AssemblyName => this.DeclaringType.AssemblyName;
public abstract string Name { get; }
public bool IsStatic { get; }
public int MetadataToken => this.metadataToken ?? this.cachedMemberInfo?.GetMetadataTokenSafe() ?? 0;
public MemberInfo MemberInfo => this.cachedMemberInfo ?? (this.cachedMemberInfo = this.Resolve());
internal MemberInfo MemberInfoNoResolve => this.cachedMemberInfo;
internal Resolver Resolver => this.DeclaringType.Resolver;
public static MemberRef Get(MemberInfo member, Resolver resolver)
{
if (member == null)
{
return null;
}
switch (member.MemberType)
{
case MemberTypes.Field:
return new FieldRef((FieldInfo)member, resolver);
case MemberTypes.Constructor:
case MemberTypes.Method:
return new MethodRef((MethodInfo)member, resolver);
case MemberTypes.Property:
return new PropertyRef((PropertyInfo)member, resolver);
default:
throw new NotSupportedException();
}
}
public virtual bool Equals(MemberRef other)
{
if (other == null || !this.GetType().IsEquivalentTo(other.GetType()))
{
return false;
}
if (this.cachedMemberInfo != null && other.cachedMemberInfo != null)
{
if (this.cachedMemberInfo == other.cachedMemberInfo)
{
return true;
}
}
if (this.metadataToken.HasValue && other.metadataToken.HasValue && this.DeclaringType.AssemblyId.Equals(other.DeclaringType.AssemblyId))
{
if (this.metadataToken.Value != other.metadataToken.Value)
{
return false;
}
}
else
{
if (!this.EqualsByTypeLocalMetadata(other))
{
return false;
}
}
return EqualityComparer<TypeRef>.Default.Equals(this.DeclaringType, other.DeclaringType);
}
/// <summary>
/// Gets a value indicating whether this instance is equivalent to another one,
/// based only on metadata that describes this member, assuming the declaring types are equal.
/// </summary>
/// <param name="other">The instance to compare with. This may be assumed to always be an instance of the same type.</param>
/// <returns><c>true</c> if the local metadata on the member are equal; <c>false</c> otherwise.</returns>
protected abstract bool EqualsByTypeLocalMetadata(MemberRef other);
protected abstract MemberInfo Resolve();
internal abstract void GetInputAssemblies(ISet<AssemblyName> assemblies);
public override int GetHashCode()
{
// Derived types must override this.
throw new NotImplementedException();
}
public override bool Equals(object obj)
{
return obj is MemberRef && this.Equals((MemberRef)obj);
}
}
}