diff --git a/examples/Demo/AssetExplorer/Components/Controls/PreviewCard.razor.cs b/examples/Demo/AssetExplorer/Components/Controls/PreviewCard.razor.cs index 49ff584c9f..a15d15b35b 100644 --- a/examples/Demo/AssetExplorer/Components/Controls/PreviewCard.razor.cs +++ b/examples/Demo/AssetExplorer/Components/Controls/PreviewCard.razor.cs @@ -39,7 +39,7 @@ private string FullName if (Emoji != null) { - return $"{Emoji.Group}.{Emoji.Style}.{Emoji.Skintone}.{Emoji.Name}"; + return $"{Emoji.Group}.{Emoji.Style}.{Emoji.Skintone}.{Emoji.Name}".Replace("_", ""); } return string.Empty; @@ -51,7 +51,7 @@ public async void CopyToClipboardAsync() if (Icon != null) { // Icons.[IconVariant].[IconSize].[IconName] - var value = $"Value=\"@(new Icons.{FullName}())\""; + var value = $"Value=\"@(new Microsoft.FluentUI.AspNetCore.Components.Icons.{FullName}())\""; var color = IconColor == Color.Accent ? string.Empty : $" Color=\"@Color.{IconColor}\""; var code = $""; @@ -72,7 +72,7 @@ public async void CopyToClipboardAsync() if (Emoji != null) { // Emojis.[EmojiGroup].[EmojiStyle].[EmojiSkintone].[EmojiName] - var value = $"Value=\"@(new Emojis.{FullName}())\""; + var value = $"Value=\"@(new Microsoft.FluentUI.AspNetCore.Components.Emojis.{FullName}())\""; var code = $""; diff --git a/examples/Demo/AssetExplorer/Components/Pages/EmojiExplorer.razor.cs b/examples/Demo/AssetExplorer/Components/Pages/EmojiExplorer.razor.cs index 0d50f0dfd6..d67e69f37b 100644 --- a/examples/Demo/AssetExplorer/Components/Pages/EmojiExplorer.razor.cs +++ b/examples/Demo/AssetExplorer/Components/Pages/EmojiExplorer.razor.cs @@ -49,9 +49,9 @@ private async Task StartNewSearchAsync() EmojisFound = [ .. EmojiExtensions.AllEmojis - .Where(i => i.Style == Criteria.Style - && (string.IsNullOrWhiteSpace(Criteria.SearchTerm) ? true : i.Name.Contains(Criteria.SearchTerm, StringComparison.InvariantCultureIgnoreCase))) - .OrderBy(i => i.Name) + .Where(i => i.Style == Criteria.Style + && (string.IsNullOrWhiteSpace(Criteria.SearchTerm) ? true : i.Name.Contains(Criteria.SearchTerm, StringComparison.InvariantCultureIgnoreCase))) + .OrderBy(i => i.Name) , ]; diff --git a/src/Core/Components/Emojis/EmojiExtensions.cs b/src/Core/Components/Emojis/EmojiExtensions.cs index d9f67acb73..3ad1d85e91 100644 --- a/src/Core/Components/Emojis/EmojiExtensions.cs +++ b/src/Core/Components/Emojis/EmojiExtensions.cs @@ -3,6 +3,7 @@ // ------------------------------------------------------------------------ using System.Diagnostics.CodeAnalysis; +using System.Reflection; namespace Microsoft.FluentUI.AspNetCore.Components; @@ -10,31 +11,32 @@ namespace Microsoft.FluentUI.AspNetCore.Components; public static partial class EmojiExtensions { private const string Namespace = "Microsoft.FluentUI.AspNetCore.Components"; - private const string LibraryName = "Microsoft.FluentUI.AspNetCore.Components.Emojis"; + private const string LibraryName = "Microsoft.FluentUI.AspNetCore.Components.Emojis.{0}"; // {0} must be replaced with the "Group": SmileysEmotion, PeopleBody, etc. /// /// Returns a new instance of the emoji. /// /// /// This method requires dynamic access to code. This code may be removed by the trimmer. + /// If the assembly is not yet loaded, it will be loaded by the method `Assembly.Load`. + /// To avoid any issues, the assembly must be loaded before calling this method (e.g. adding an emoji in your code). /// /// /// Raised when the is not found in predefined emojis. [RequiresUnreferencedCode("This method requires dynamic access to code. This code may be removed by the trimmer.")] public static CustomEmoji GetInstance(this EmojiInfo emoji) { - var assembly = AppDomain.CurrentDomain - .GetAssemblies() - .FirstOrDefault(i => i.ManifestModule.Name.StartsWith(LibraryName, StringComparison.Ordinal)); + var group = emoji.Group.ToString().Replace("_", string.Empty); + var assemblyName = string.Format(LibraryName, group); + var assembly = GetAssembly(assemblyName); if (assembly != null) { var allEmojis = assembly.GetTypes() .Where(i => i.BaseType == typeof(Emoji)); - // Ex. Microsoft.FluentUI.AspNetCore.Components.Emojis+Activities+Color+Default+Baseball - var group = emoji.Group.ToString().Replace("_", string.Empty); - var emojiFullName = $"{Namespace}.Emojis+{group}+{emoji.Style}+{emoji.Skintone}+{emoji.Name}"; + // Ex. Microsoft.FluentUI.AspNetCore.Components.Emojis.Activities.Color.Default+Baseball + var emojiFullName = $"{Namespace}.Emojis.{group}.{emoji.Style}.{emoji.Skintone}+{emoji.Name}"; var emojiType = allEmojis.FirstOrDefault(i => i.FullName == emojiFullName); if (emojiType != null) @@ -47,7 +49,7 @@ public static CustomEmoji GetInstance(this EmojiInfo emoji) } } - throw new ArgumentException($"Emoji '{emoji.Name}' not found."); + throw new ArgumentException($"Emoji 'Emojis.{group}.{emoji.Style}.{emoji.Skintone}.{emoji.Name}' not found."); } /// @@ -61,21 +63,24 @@ public static CustomEmoji GetInstance(this EmojiInfo emoji) [RequiresUnreferencedCode("This method requires dynamic access to code. This code may be removed by the trimmer.")] public static IEnumerable GetAllEmojis() { - var assembly = AppDomain.CurrentDomain - .GetAssemblies() - .FirstOrDefault(i => i.ManifestModule.Name.StartsWith(LibraryName, StringComparison.Ordinal)); + var allIcons = new List(); - if (assembly != null) + foreach (var group in Enum.GetValues(typeof(EmojiGroup)).Cast()) { - var allTypes = assembly.GetTypes() - .Where(i => i.BaseType == typeof(Emoji)); + var assemblyName = string.Format(LibraryName, group.ToString().Replace("_", string.Empty)); + var assembly = GetAssembly(assemblyName); - var allEmojis = allTypes.Select(type => Activator.CreateInstance(type) as EmojiInfo ?? new EmojiInfo()); + if (assembly != null) + { + var allTypes = assembly.GetTypes() + .Where(i => i.BaseType == typeof(Emoji) + && i.Name != nameof(CustomEmoji)); - return allEmojis ?? Array.Empty(); + allIcons.AddRange(allTypes.Select(type => Activator.CreateInstance(type) as EmojiInfo ?? new EmojiInfo())); + } } - return Array.Empty(); + return allIcons; } /// @@ -86,4 +91,21 @@ public static IEnumerable AllEmojis return GetAllEmojis(); } } + + /// + private static Assembly? GetAssembly(string assemblyName) + { + try + { + return AppDomain.CurrentDomain + .GetAssemblies() + .FirstOrDefault(i => i.ManifestModule.Name == assemblyName + ".dll") + ?? Assembly.Load(assemblyName); + + } + catch (Exception) + { + return null; + } + } } diff --git a/src/Core/Components/Icons/IconsExtensions.cs b/src/Core/Components/Icons/IconsExtensions.cs index b7d675c4d4..cc14f4b48a 100644 --- a/src/Core/Components/Icons/IconsExtensions.cs +++ b/src/Core/Components/Icons/IconsExtensions.cs @@ -3,6 +3,7 @@ // ------------------------------------------------------------------------ using System.Diagnostics.CodeAnalysis; +using System.Reflection; namespace Microsoft.FluentUI.AspNetCore.Components; @@ -10,7 +11,7 @@ namespace Microsoft.FluentUI.AspNetCore.Components; public static partial class IconsExtensions { private const string Namespace = "Microsoft.FluentUI.AspNetCore.Components"; - private const string LibraryName = "Microsoft.FluentUI.AspNetCore.Components.Icons"; + private const string LibraryName = "Microsoft.FluentUI.AspNetCore.Components.Icons.{0}"; // {0} must be replaced with the "Variant": Regular, Filled, etc. /// /// Returns a new instance of the icon. @@ -18,22 +19,23 @@ public static partial class IconsExtensions /// The to instantiate. /// /// This method requires dynamic access to code. This code may be removed by the trimmer. + /// If the assembly is not yet loaded, it will be loaded by the method `Assembly.Load`. + /// To avoid any issues, the assembly must be loaded before calling this method (e.g. adding an icon in your code). /// /// /// Raised when the is not found in predefined icons. [RequiresUnreferencedCode("This method requires dynamic access to code. This code may be removed by the trimmer.")] public static CustomIcon GetInstance(this IconInfo icon) { - var assembly = AppDomain.CurrentDomain - .GetAssemblies() - .FirstOrDefault(i => i.ManifestModule.Name.StartsWith(LibraryName, StringComparison.Ordinal)); + var assemblyName = string.Format(LibraryName, icon.Variant); + var assembly = GetAssembly(assemblyName); if (assembly != null) { var allIcons = assembly.GetTypes() .Where(i => i.BaseType == typeof(Icon)); - // Ex. Microsoft.FluentUI.AspNetCore.Components.Icons+Filled+Size10+PresenceAvailable + // Ex. Microsoft.FluentUI.AspNetCore.Components.Icons.Filled.Size10+PresenceAvailable var iconFullName = $"{Namespace}.Icons.{icon.Variant}.Size{(int)icon.Size}+{icon.Name}"; var iconType = allIcons.FirstOrDefault(i => i.FullName == iconFullName); @@ -47,7 +49,7 @@ public static CustomIcon GetInstance(this IconInfo icon) } } - throw new ArgumentException($"Icon '{icon.Name}' not found."); + throw new ArgumentException($"Icon 'Icons.{icon.Variant}.Size{(int)icon.Size}.{icon.Name}' not found."); } /// @@ -61,22 +63,24 @@ public static CustomIcon GetInstance(this IconInfo icon) [RequiresUnreferencedCode("This method requires dynamic access to code. This code may be removed by the trimmer.")] public static IEnumerable GetAllIcons() { - var assembly = AppDomain.CurrentDomain - .GetAssemblies() - .FirstOrDefault(i => i.ManifestModule.Name.StartsWith(LibraryName, StringComparison.Ordinal)); + var allIcons = new List(); - if (assembly != null) + foreach (var variant in Enum.GetValues(typeof(IconVariant)).Cast()) { - var allTypes = assembly.GetTypes() - .Where(i => i.BaseType == typeof(Icon) - && i.Name != nameof(CustomIcon)); + var assemblyName = string.Format(LibraryName, variant); + var assembly = GetAssembly(assemblyName); - var allIcons = allTypes.Select(type => Activator.CreateInstance(type) as IconInfo ?? new IconInfo()); + if (assembly != null) + { + var allTypes = assembly.GetTypes() + .Where(i => i.BaseType == typeof(Icon) + && i.Name != nameof(CustomIcon)); - return allIcons ?? []; + allIcons.AddRange(allTypes.Select(type => Activator.CreateInstance(type) as IconInfo ?? new IconInfo())); + } } - return []; + return allIcons; } /// @@ -87,4 +91,21 @@ public static IEnumerable AllIcons return GetAllIcons(); } } + + /// + private static Assembly? GetAssembly(string assemblyName) + { + try + { + return AppDomain.CurrentDomain + .GetAssemblies() + .FirstOrDefault(i => i.ManifestModule.Name == assemblyName + ".dll") + ?? Assembly.Load(assemblyName); + + } + catch (Exception) + { + return null; + } + } }