Skip to content

Commit 5c4a7d6

Browse files
committed
Add public cache key struct and symbol data views
Introduce SymbolReflectionInfoCacheKey as a public, strongly-typed cache key for symbol reflection info, with context validation and equality. Refactor SymbolReflectionInfoCache to map internal keys to public keys and update cleanup logic. Replace internal TypeData access with ITypeDataView for public API. Add PropertyDataView and EventDataView classes to expose safe, read-only symbol info. Update ISymbolInfoDataView to include CacheKey property. Improve encapsulation and memory safety for ALC scenarios.
1 parent 3a409ed commit 5c4a7d6

18 files changed

+524
-292
lines changed

src/BionicCode.Utilities.Reflection/DelegateProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2002,7 +2002,7 @@ private static Expression CreateTargetTypeMismatchExceptionExpression(PropertyDa
20022002
typeof(string),
20032003
])!;
20042004

2005-
TypeData helperExtensionsCommonTypeData = SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntry(typeof(ReflectionHelperExtensions));
2005+
TypeData helperExtensionsCommonTypeData = SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntryInternal(typeof(ReflectionHelperExtensions));
20062006
const string extensionMethodName = nameof(ReflectionHelperExtensions.ToFullyQualifiedSignatureName);
20072007
var typeCacheKey = SymbolReflectionInfoCacheKeyInternal.CreateForType(typeof(Type));
20082008
MethodData toFullyQualifiedSignatureNameExtensionMethodData = helperExtensionsCommonTypeData.Methods[extensionMethodName, new MethodParameterInfo(typeCacheKey)];

src/BionicCode.Utilities.Reflection/EventData.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ private void ThrowIfInvalidMethodArguments(object?[]? args)
143143
internal MethodData EventInvokerMethodData => _invocatorMethodData ??= EventHandlerTypeData?.DelegateInvokeMethodData!;
144144

145145
internal TypeData EventHandlerTypeData => _eventHandlerTypeData ??= EventInfo.EventHandlerType is Type eventHandlerType
146-
? SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntry(eventHandlerType)
146+
? SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntryInternal(eventHandlerType)
147147
: throw new NotSupportedException($"The underlying '{typeof(EventInfo).FullName}' for event '{EventInfo.Name}' does not have an event handler type.");
148148

149149
internal EventInfo EventInfo { get; }
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
namespace BionicCode.Utilities.Net.Reflection;
2+
3+
using System;
4+
using System.Reflection;
5+
6+
public class EventDataView : IEventDataView
7+
{
8+
internal EventDataView(SymbolReflectionInfoCacheKey cacheKey) => CacheKey = cacheKey;
9+
10+
public AccessModifier AccessModifier => SymbolReflectionInfoCache.GetOrCreateEventDataCacheEntry(CacheKey).AccessModifier;
11+
public IMethodDataView AddMethodDataView { get; }
12+
public string AssemblyName { get; }
13+
public bool CanAdd { get; }
14+
public bool CanRemove { get; }
15+
public RuntimeTypeHandle DeclaringInterfaceHandle { get; }
16+
public RuntimeTypeHandle DeclaringTypeHandle { get; }
17+
public string DisplayName { get; }
18+
public ITypeDataView EventHandlerTypeDataView { get; }
19+
public IMethodDataView EventInvokerMethodDataView { get; }
20+
public string FullyQualifiedDisplayName { get; }
21+
public string FullyQualifiedRuntimeSignature { get; }
22+
public string FullyQualifiedSignature { get; }
23+
public RuntimeTypeHandle ImplementingTypeHandle { get; }
24+
public bool IsAssembly { get; }
25+
public bool IsExplicitInterfaceImplementation { get; }
26+
public bool IsFamily { get; }
27+
public bool IsFamilyAndAssembly { get; }
28+
public bool IsFamilyOrAssembly { get; }
29+
public bool IsOverride { get; }
30+
public bool IsPrivate { get; }
31+
public bool IsPublic { get; }
32+
public bool IsStatic { get; }
33+
public IMethodDataView RemoveMethodDataView { get; }
34+
public string RuntimeShortCompactSignature { get; }
35+
public string RuntimeShortSignature { get; }
36+
public string RuntimeSignature { get; }
37+
public string ShortCompactSignature { get; }
38+
public string ShortDisplayName { get; }
39+
public string ShortSignature { get; }
40+
public string Signature { get; }
41+
public SymbolComponentInfo SymbolComponentInfo { get; }
42+
public IList<CustomAttributeData> AttributeData { get; }
43+
public BindingFlags BindingFlagsVisibilityMask { get; }
44+
public string Namespace { get; }
45+
public int FormattingIndentation { get; set; }
46+
public string IndentationString { get; }
47+
public string Name { get; }
48+
public SymbolAttributes SymbolAttributes { get; }
49+
SymbolAttributes ISymbolInfoDataView.SymbolAttributes { get; }
50+
private ITypeDataView DeclaringTypeDataView { get; }
51+
public SymbolReflectionInfoCacheKey CacheKey { get; }
52+
public SymbolKind SymbolKind { get; }
53+
public IMethodDataView AddMethodData { get; }
54+
public ITypeDataView EventHandlerTypeData { get; }
55+
public IMethodDataView EventInvokerMethodData { get; }
56+
public IMethodDataView RemoveMethodData { get; }
57+
public ITypeDataView DeclaringTypData { get; }
58+
public ITypeDataView ImplementingTypData { get; }
59+
60+
public void AddEventHandler(object eventSource, Delegate handler) => throw new NotImplementedException();
61+
public void AddEventHandler<TEventSource>(TEventSource eventSource, Delegate handler) => throw new NotImplementedException();
62+
public object? RaiseEvent(object? target, params object?[]? arguments) => throw new NotImplementedException();
63+
public void RemoveEventHandler(object eventSource, Delegate handler) => throw new NotImplementedException();
64+
public void RemoveEventHandler<TEventSource>(TEventSource eventSource, Delegate handler) => throw new NotImplementedException();
65+
}

src/BionicCode.Utilities.Reflection/FieldData.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ internal void SetValue(object? target, object? value)
209209

210210
internal override bool IsStatic => _isStatic ??= FieldInfo.IsStatic;
211211

212-
internal TypeData FieldTypeData => _fieldTypeData ??= SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntry(FieldInfo.FieldType);
212+
internal TypeData FieldTypeData => _fieldTypeData ??= SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntryInternal(FieldInfo.FieldType);
213213

214214
internal bool IsRef => _isRef ??= FieldTypeData.IsByRef;
215215

src/BionicCode.Utilities.Reflection/IPropertyDataView.cs

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -31,66 +31,3 @@ public interface IPropertyDataView : IMemberDataView, ISymbolInfoDataView
3131
void SetValue(object? target, object? value);
3232
void SetValue<TTarget, TValue>(TTarget target, TValue value) where TTarget : class;
3333
}
34-
35-
public class PropertyDataView : IPropertyDataView
36-
{
37-
public bool CanRead { get; }
38-
public bool CanWrite { get; }
39-
public AccessModifier GetAccessorAccessModifier { get; }
40-
public bool IsIndexer { get; }
41-
public bool IsInit { get; }
42-
public bool IsOverride { get; }
43-
public bool IsReadOnly { get; }
44-
public bool IsSealed { get; }
45-
public bool IsSetMethodReadOnly { get; }
46-
public IMethodDataView? PropertyGetMethodData { get; }
47-
public IParameterListView PropertyGetMethodParameters { get; }
48-
public IMethodDataView? PropertySetMethodData { get; }
49-
public IParameterListView PropertySetMethodParameters { get; }
50-
public ITypeDataView? PropertyTypeData { get; }
51-
public AccessModifier SetAccessorAccessModifier { get; }
52-
public AccessModifier AccessModifier { get; }
53-
public BindingFlags BindingFlagsVisibilityMask { get; }
54-
public ITypeDataView? DeclaringTypData { get; }
55-
public RuntimeTypeHandle DeclaringTypeHandle { get; }
56-
public RuntimeTypeHandle ImplementingTypeHandle { get; }
57-
public ITypeDataView? ImplementingTypData { get; }
58-
public bool IsAssembly { get; }
59-
public bool IsExplicitInterfaceImplementation { get; }
60-
public bool IsFamily { get; }
61-
public bool IsFamilyAndAssembly { get; }
62-
public bool IsFamilyOrAssembly { get; }
63-
public bool IsPrivate { get; }
64-
public bool IsPublic { get; }
65-
public bool IsStatic { get; }
66-
public string? AssemblyName { get; }
67-
public string? Namespace { get; }
68-
public IList<CustomAttributeData>? AttributeData { get; }
69-
public string? DisplayName { get; }
70-
public int FormattingIndentation { get; set; }
71-
public string? FullyQualifiedDisplayName { get; }
72-
public string? FullyQualifiedRuntimeSignature { get; }
73-
public string? FullyQualifiedSignature { get; }
74-
public string? IndentationString { get; }
75-
public string? Name { get; }
76-
public string? RuntimeShortCompactSignature { get; }
77-
public string? RuntimeShortSignature { get; }
78-
public string? RuntimeSignature { get; }
79-
public string? ShortCompactSignature { get; }
80-
public string? ShortDisplayName { get; }
81-
public string? ShortSignature { get; }
82-
public string? Signature { get; }
83-
public SymbolAttributes SymbolAttributes { get; }
84-
public SymbolComponentInfo? SymbolComponentInfo { get; }
85-
public SymbolKind SymbolKind { get; }
86-
87-
public object? GetIndexerValue(object? target, object?[] indexerPropertyParameters) => throw new NotImplementedException();
88-
public TValue GetIndexerValue<TTarget, TValue, TIndex>(TTarget target, params TIndex[] indexerPropertyParameters) => throw new NotImplementedException();
89-
public TValue GetIndexerValue<TTarget, TValue>(TTarget target, params object[] indexerPropertyParameters) => throw new NotImplementedException();
90-
public object? GetValue(object? target) => throw new NotImplementedException();
91-
public TValue GetValue<TTarget, TValue>(TTarget target) => throw new NotImplementedException();
92-
public void SetIndexerValue(object? target, object? value, object?[]? indexerPropertyIndex = null) => throw new NotImplementedException();
93-
public void SetStructValue<TTarget, TValue>(ref TTarget target, TValue value, object[]? indexerPropertyIndex = null) where TTarget : struct => throw new NotImplementedException();
94-
public void SetValue(object? target, object? value) => throw new NotImplementedException();
95-
public void SetValue<TTarget, TValue>(TTarget target, TValue value) where TTarget : class => throw new NotImplementedException();
96-
}

src/BionicCode.Utilities.Reflection/ISymbolInfoDataView.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
public interface ISymbolInfoDataView
77
{
8+
SymbolReflectionInfoCacheKey CacheKey { get; }
89
string AssemblyName { get; }
910
string Namespace { get; }
1011
IList<CustomAttributeData> AttributeData { get; }

src/BionicCode.Utilities.Reflection/MemberData.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ private BindingFlags ComputeVisibilityBindingFlagsMask()
4545

4646
internal TypeData DeclaringTypeData
4747
=> _declaringTypeData ??= Type.GetTypeFromHandle(DeclaringTypeHandle) is Type declaringType
48-
? SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntry(declaringType)
48+
? SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntryInternal(declaringType)
4949
: throw new InvalidOperationException($"The runtime type handle returned from the property '{nameof(DeclaringTypeHandle)}' is not valid.");
5050

5151
internal TypeData ImplementingTypeData
5252
=> _implementingTypeData ??= Type.GetTypeFromHandle(ImplementingTypeHandle) is Type implementingType
53-
? SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntry(implementingType)
53+
? SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntryInternal(implementingType)
5454
: throw new InvalidOperationException($"The runtime type handle returned from the property '{nameof(ImplementingTypeHandle)}' is not valid.");
5555

5656
internal override string Namespace

src/BionicCode.Utilities.Reflection/MethodData.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1196,7 +1196,7 @@ internal bool IsAwaitableGenericTask
11961196

11971197
internal override string AssemblyName => _assemblyName ??= DeclaringTypeData.AssemblyName;
11981198

1199-
internal TypeData ReturnTypeData => _returnTypeData ??= SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntry(MethodInfo.ReturnType);
1199+
internal TypeData ReturnTypeData => _returnTypeData ??= SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntryInternal(MethodInfo.ReturnType);
12001200

12011201
internal bool IsGenericMethod => _isGenericMethod ??= MethodInfo.IsGenericMethod;
12021202

src/BionicCode.Utilities.Reflection/ParameterData.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ internal ParameterData(SymbolReflectionInfoCacheKeyInternal symbolInfoDataCacheK
169169
_ => throw new NotImplementedException(),
170170
};
171171

172-
internal TypeData ParameterTypeData => _parameterTypeData ??= SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntry(ParameterInfo.ParameterType);
172+
internal TypeData ParameterTypeData => _parameterTypeData ??= SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntryInternal(ParameterInfo.ParameterType);
173173

174174
internal TypeData DeclaringTypeData => _declaringTypeData ??= MemberData.DeclaringTypeData;
175175

src/BionicCode.Utilities.Reflection/PropertyData.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -896,7 +896,7 @@ internal AccessModifier GetAccessorAccessModifier
896896
}
897897
}
898898

899-
internal TypeData PropertyTypeData => _propertyTypeData ??= SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntry(PropertyInfo.PropertyType);
899+
internal TypeData PropertyTypeData => _propertyTypeData ??= SymbolReflectionInfoCache.GetOrCreateSymbolInfoDataCacheEntryInternal(PropertyInfo.PropertyType);
900900

901901
internal PropertyInfo PropertyInfo { get; }
902902

0 commit comments

Comments
 (0)