File: XamlCache.cs
Web Access
Project: src\src\Controls\src\Build.Tasks\Controls.Build.Tasks.csproj (Microsoft.Maui.Controls.Build.Tasks)
using System;
using System.Collections.Generic;
using Microsoft.Maui.Controls.XamlC;
using Mono.Cecil;
using Mono.Cecil.Cil;
 
namespace Microsoft.Maui.Controls.Build.Tasks;
 
/// <summary>
/// Class for caching various Mono.Cecil objects
/// </summary>
class XamlCache
{
	readonly Dictionary<ModuleDefinition, IList<XmlnsDefinitionAttribute>> _xmlnsDefinitions = new();
	readonly Dictionary<TypeReference, TypeDefinition> _resolvedTypes = new();
	readonly Dictionary<(ModuleDefinition module, string fieldRefKey), FieldReference> _fieldReferenceCache = new();
	readonly Dictionary<(ModuleDefinition module, string typeKey), TypeReference> _typeReferenceCache = new();
	readonly Dictionary<(ModuleDefinition module, string methodRefKey), MethodReference> _methodReferenceCache = new();
	readonly Dictionary<(ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName)), TypeDefinition> _typeDefinitionCache = new();
	readonly Dictionary<VariableDefinition, ICollection<string>> _resourceNamesInUse = new();
	Dictionary<TypeReference, Type> _knownCompiledTypeConverters;
 
	static TValue GetOrAdd<TKey, TValue>(Dictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> valueFactory)
	{
		if (!dictionary.TryGetValue(key, out TValue value))
		{
			value = dictionary[key] = valueFactory(key);
		}
		return value;
	}
 
	public IList<XmlnsDefinitionAttribute> GetXmlsDefinitions(ModuleDefinition module, Func<ModuleDefinition, IList<XmlnsDefinitionAttribute>> valueFactory) =>
		GetOrAdd(_xmlnsDefinitions, module, valueFactory);
 
	public TypeDefinition Resolve(TypeReference typeReference) =>
		GetOrAdd(_resolvedTypes, typeReference, t => t.Resolve());
 
	public FieldReference GetOrAddFieldReference((ModuleDefinition module, string fieldRefKey) key, Func<(ModuleDefinition module, string fieldRefKey), FieldReference> valueFactory) =>
		GetOrAdd(_fieldReferenceCache, key, valueFactory);
 
	public TypeReference GetOrAddTypeReference(ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type) =>
		GetOrAdd(_typeReferenceCache, (module, type.ToString()), x => x.module.ImportReference(x.module.GetTypeDefinition(this, type)));
 
	public TypeReference GetOrAddTypeReference(ModuleDefinition module, string typeKey, Func<(ModuleDefinition module, string typeKey), TypeReference> valueFactory) =>
		GetOrAdd(_typeReferenceCache, (module, typeKey), valueFactory);
 
	public MethodReference GetOrAddMethodReference(ModuleDefinition module, string methodRefKey, Func<(ModuleDefinition module, string methodRefKey), MethodReference> valueFactory) =>
		GetOrAdd(_methodReferenceCache, (module, methodRefKey), valueFactory);
 
	public TypeDefinition GetOrAddTypeDefinition(ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type, Func<(ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName)), TypeDefinition> valueFactory) =>
		GetOrAdd(_typeDefinitionCache, (module, type), valueFactory);
 
	public ICollection<string> GetResourceNamesInUse(VariableDefinition variableDefinition) =>
		GetOrAdd(_resourceNamesInUse, variableDefinition, _ => new HashSet<string>(StringComparer.Ordinal));
 
	public Dictionary<TypeReference, Type> GetKnownCompiledTypeConverters(ModuleDefinition module) => _knownCompiledTypeConverters ??= new(TypeRefComparer.Default)
	{
		{ module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "ThicknessTypeConverter")), typeof(ThicknessTypeConverter) },
		{ module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "CornerRadiusTypeConverter")), typeof(CornerRadiusTypeConverter) },
		{ module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "EasingTypeConverter")), typeof(EasingTypeConverter) },
		{ module.ImportReference(this, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics.Converters", "ColorTypeConverter")), typeof(ColorTypeConverter) },
		{ module.ImportReference(this, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics.Converters", "PointTypeConverter")), typeof(PointTypeConverter) },
		{ module.ImportReference(this, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics.Converters", "RectTypeConverter")), typeof(RectangleTypeConverter) },
		{ module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexJustifyTypeConverter")), typeof(EnumTypeConverter<Layouts.FlexJustify>) },
		{ module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexDirectionTypeConverter")), typeof(EnumTypeConverter<Layouts.FlexDirection>) },
		{ module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexAlignContentTypeConverter")), typeof(EnumTypeConverter<Layouts.FlexAlignContent>) },
		{ module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexAlignItemsTypeConverter")), typeof(EnumTypeConverter<Layouts.FlexAlignItems>) },
		{ module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexAlignSelfTypeConverter")), typeof(EnumTypeConverter<Layouts.FlexAlignSelf>) },
		{ module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexWrapTypeConverter")), typeof(EnumTypeConverter<Layouts.FlexWrap>) },
		{ module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexBasisTypeConverter")), typeof(FlexBasisTypeConverter) },
	};
 
	// State used by SetPropertiesVisitor
	public int DataTemplateCount { get; set; }
	public int TypedBindingCount { get; set; }
}