File: CompiledMarkupExtensions\StaticExtension.cs
Web Access
Project: src\src\Controls\src\Build.Tasks\Controls.Build.Tasks.csproj (Microsoft.Maui.Controls.Build.Tasks)
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using Microsoft.Maui.Controls.Xaml;
using Mono.Cecil;
using Mono.Cecil.Cil;
using static System.String;
 
namespace Microsoft.Maui.Controls.Build.Tasks
{
	class StaticExtension : ICompiledMarkupExtension
	{
		public IEnumerable<Instruction> ProvideValue(IElementNode node, ModuleDefinition module, ILContext context, out TypeReference memberRef)
		{
			INode ntype;
			if (!node.Properties.TryGetValue(new XmlName("", "Member"), out ntype))
				ntype = node.CollectionItems[0];
			var member = ((ValueNode)ntype).Value as string;
 
			if (IsNullOrEmpty(member) || !member.Contains("."))
				throw new BuildException(BuildExceptionCode.XStaticSyntax, node as IXmlLineInfo, null);
 
			var dotIdx = member.LastIndexOf('.');
			var typename = member.Substring(0, dotIdx);
			var membername = member.Substring(dotIdx + 1);
 
			var typeRef = module.ImportReference(XmlTypeExtensions.GetTypeReference(context.Cache, typename, module, node as BaseNode));
			var fieldRef = GetFieldReference(context.Cache, typeRef, membername, module);
			var propertyDef = GetPropertyDefinition(context.Cache, typeRef, membername, module);
 
			if (fieldRef == null && propertyDef == null)
				throw new BuildException(BuildExceptionCode.XStaticResolution, node as IXmlLineInfo, null, membername, typename);
 
			var fieldDef = fieldRef?.Resolve();
			if (fieldRef != null)
			{
				memberRef = fieldRef.FieldType;
				if (!fieldDef.HasConstant)
					return new[] { Instruction.Create(OpCodes.Ldsfld, fieldRef) };
 
				//Constants can be numbers, Boolean values, strings, or a null reference. (https://msdn.microsoft.com/en-us/library/e6w8fe1b.aspx)
				if (TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.Boolean))
					return new[] { Instruction.Create(((bool)fieldDef.Constant) ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0) };
				if (TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.String))
					return new[] { Instruction.Create(OpCodes.Ldstr, (string)fieldDef.Constant) };
				if (fieldDef.Constant == null)
					return new[] { Instruction.Create(OpCodes.Ldnull) };
				if (TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.Char))
					return new[] { Instruction.Create(OpCodes.Ldc_I4, (char)fieldDef.Constant) };
				if (TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.Single))
					return new[] { Instruction.Create(OpCodes.Ldc_R4, (float)fieldDef.Constant) };
				if (TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.Double))
					return new[] { Instruction.Create(OpCodes.Ldc_R8, (double)fieldDef.Constant) };
				if (TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.Byte) || TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.Int16) || TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.Int32))
					return new[] { Instruction.Create(OpCodes.Ldc_I4, (int)fieldDef.Constant) };
				if (TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.SByte) || TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.UInt16) || TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.UInt32))
					return new[] { Instruction.Create(OpCodes.Ldc_I4, (uint)fieldDef.Constant) };
				if (TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.Int64))
					return new[] { Instruction.Create(OpCodes.Ldc_I8, (long)fieldDef.Constant) };
				if (TypeRefComparer.Default.Equals(memberRef, module.TypeSystem.UInt64))
					return new[] { Instruction.Create(OpCodes.Ldc_I8, (ulong)fieldDef.Constant) };
 
				//enum values
				if (memberRef.ResolveCached(context.Cache).IsEnum)
				{
					if (fieldDef.Constant is long)
						return new[] { Instruction.Create(OpCodes.Ldc_I8, (long)fieldDef.Constant) };
					if (fieldDef.Constant is ulong)
						return new[] { Instruction.Create(OpCodes.Ldc_I8, (ulong)fieldDef.Constant) };
					if (fieldDef.Constant is uint)
						return new[] { Instruction.Create(OpCodes.Ldc_I4, (uint)fieldDef.Constant) };
					//everything else will cast just fine to an int
					return new[] { Instruction.Create(OpCodes.Ldc_I4, (int)fieldDef.Constant) };
				}
			}
 
			memberRef = propertyDef.PropertyType;
			var getterDef = module.ImportReference(propertyDef.GetMethod);
			return new[] { Instruction.Create(OpCodes.Call, getterDef) };
		}
 
		public static FieldReference GetFieldReference(XamlCache cache, TypeReference typeRef, string fieldName, ModuleDefinition module)
		{
			FieldReference fRef = typeRef.GetField(cache, fd => fd.Name == fieldName
														&& fd.IsStatic
														&& IsPublicOrVisibleInternal(fd, module), out TypeReference declaringTypeReference);
			if (fRef != null)
			{
				fRef = module.ImportReference(fRef.ResolveGenericParameters(declaringTypeReference));
				fRef.FieldType = module.ImportReference(fRef.FieldType);
			}
			return fRef;
		}
 
		static bool IsPublicOrVisibleInternal(FieldDefinition fd, ModuleDefinition module)
		{
			if (fd.IsPublic)
				return true;
			if (fd.IsAssembly)
			{
				if (fd.Module == module)
					return true;
				if (fd.Module.IsVisibleInternal(module))
					return true;
			}
			return false;
		}
 
		public static PropertyDefinition GetPropertyDefinition(XamlCache cache, TypeReference typeRef, string propertyName, ModuleDefinition module)
		{
			PropertyDefinition pDef = typeRef.GetProperty(cache, pd => pd.Name == propertyName
																&& IsPublicOrVisibleInternal(pd.GetMethod, module)
																&& pd.GetMethod.IsStatic, out TypeReference declaringTypeReference);
			return pDef;
		}
 
		static bool IsPublicOrVisibleInternal(MethodDefinition md, ModuleDefinition module)
		{
			if (md.IsPublic)
				return true;
			if (md.IsAssembly)
			{
				if (md.Module == module)
					return true;
				if (md.Module.IsVisibleInternal(module))
					return true;
			}
			return false;
		}
	}
}