| File: ILCompiler\Metadata\EntityMap.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.MetadataTransform\ILCompiler.MetadataTransform.csproj (ILCompiler.MetadataTransform) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; namespace ILCompiler.Metadata { internal struct EntityMap<TEntity, TRecord> { private Dictionary<TEntity, TRecord> _map; public IReadOnlyCollection<TRecord> Records { get { return _map.Values; } } public IEnumerable<KeyValuePair<TEntity, TRecord>> Entries => _map; public EntityMap(IEqualityComparer<TEntity> comparer) { _map = new Dictionary<TEntity, TRecord>(comparer); } public TRecord GetOrCreate<TConcreteEntity, TConcreteRecord>(TConcreteEntity entity, Action<TConcreteEntity, TConcreteRecord> initializer) where TConcreteEntity : TEntity where TConcreteRecord : TRecord, new() { TRecord record; if (!_map.TryGetValue(entity, out record)) { // We are externalizing the allocation instead of having a 'creator' delegate // because initializer might end up recursing into GetOrCreate for the same entity. // EntityMap needs to be ready to return a pointer to the currently initialized record. // The transform doesn't care that the record is not fully initialized yet // since we're not reading it at this stage. // Example: // // class FooAttribute : Attribute // { // [FooAttribute] // public FooAttribute() // { // } // } // // In here, while we're emitting the record for FooAttribute..ctor, we need // a pointer to the record for FooAttribute..ctor because that's what the // constructor of the custom attribute applied to the constructor. TConcreteRecord concreteRecord = new TConcreteRecord(); _map.Add(entity, concreteRecord); initializer(entity, concreteRecord); return concreteRecord; } return record; } public bool TryGet(TEntity entity, out TRecord record) { return _map.TryGetValue(entity, out record); } public TConcreteRecord Create<TConcreteEntity, TConcreteRecord>(TConcreteEntity entity, Action<TConcreteEntity, TConcreteRecord> initializer) where TConcreteEntity : TEntity where TConcreteRecord : TRecord, new() { TConcreteRecord concreteRecord = new TConcreteRecord(); // Important: add to the map before calling the initializer. // For reasoning see GetOrCreate. _map.Add(entity, concreteRecord); initializer(entity, concreteRecord); return concreteRecord; } } }