< Summary - PropertyGridHelpers Code Coverage

Information
Class: PropertyGridHelpers.Attributes.DynamicPathSourceAttribute
Assembly: PropertyGridHelpers
File(s): c:\agent\_work\9\s\Code\PropertyGridHelpers\Attributes\DynamicPathSourceAttribute.cs
Tag: PropertyGridHelpers Build_2025.7.15.1_#485
Line coverage
100%
Covered lines: 20
Uncovered lines: 0
Coverable lines: 20
Total lines: 156
Line coverage: 100%
Branch coverage
100%
Covered branches: 8
Total branches: 8
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBlocks covered Blocks not covered Branch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)--100%11100%
get_PathPropertyName()--100%11100%
get_ResourceUsage()--100%11100%
DynamicPathSourceAttribute(...)20----
Get(...)200----
Get(...)--100%88100%
Get(...)170----

File(s)

c:\agent\_work\9\s\Code\PropertyGridHelpers\Attributes\DynamicPathSourceAttribute.cs

#LineLine coverage
 1using PropertyGridHelpers.Enums;
 2using System;
 3using System.ComponentModel;
 4using System.Linq;
 5
 6namespace PropertyGridHelpers.Attributes
 7{
 8#if NET8_0_OR_GREATER
 9    /// <summary>
 10    /// Specifies that the resource path used to localize or visualize this property should be
 11    /// dynamically retrieved from another property on the same object.
 12    /// </summary>
 13    /// <param name="pathPropertyName">
 14    /// The name of the property (on the same class) that returns a string resource path.
 15    /// </param>
 16    /// <param name="resourceUsage">
 17    /// The kind of resource this path will be used for. Defaults to <see cref="ResourceUsage.All"/>.
 18    /// </param>
 19    /// <remarks>
 20    /// This attribute is useful for making the resource path configurable at runtime or design time,
 21    /// especially when dealing with localized enum values, icons, or other resource-driven behaviors.
 22    ///
 23    /// You can apply multiple <see cref="DynamicPathSourceAttribute"/> instances to a single property,
 24    /// each with a different <see cref="ResourceUsage"/> value to target specific resource types (e.g. strings vs. imag
 25    ///
 26    /// Resolution logic will select the first matching path based on the requested <paramref name="resourceUsage"/>.
 27    /// </remarks>
 28    /// <example>
 29    /// Example 1: Dynamic string resource binding for enum display
 30    /// <code>
 31    /// [DynamicPathSource(nameof(MyResourcePath), ResourceUsage.Strings)]
 32    /// public MyEnum DisplayOption { get; set; }
 33    ///
 34    /// public string MyResourcePath => "MyApp.Strings.EnumResources";
 35    /// </code>
 36    ///
 37    /// Example 2: Separate image path for visual enum dropdown
 38    /// <code>
 39    /// [DynamicPathSource(nameof(ImagePath), ResourceUsage.Images)]
 40    /// public MyEnum IconChoice { get; set; }
 41    ///
 42    /// public string ImagePath => "MyApp.Images.Icons";
 43    /// </code>
 44    /// </example>
 45    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
 3246    public class DynamicPathSourceAttribute(string pathPropertyName, ResourceUsage resourceUsage = ResourceUsage.All) : 
 47#else
 48    /// <summary>
 49    /// Specifies that the resource path used to localize or visualize this property should be
 50    /// dynamically retrieved from another property on the same object.
 51    /// </summary>
 52    /// <remarks>
 53    /// This attribute is useful for making the resource path configurable at runtime or design time,
 54    /// especially when dealing with localized enum values, icons, or other resource-driven behaviors.
 55    ///
 56    /// You can apply multiple <see cref="DynamicPathSourceAttribute"/> instances to a single property,
 57    /// each with a different <see cref="ResourceUsage"/> value to target specific resource types (e.g. strings vs. imag
 58    ///
 59    /// Resolution logic will select the first matching path based on the requested resourceUsage.
 60    /// </remarks>
 61    /// <example>
 62    /// Example 1: Dynamic string resource binding for enum display
 63    /// <code>
 64    /// [DynamicPathSource(nameof(MyResourcePath), ResourceUsage.Strings)]
 65    /// public MyEnum DisplayOption { get; set; }
 66    ///
 67    /// public string MyResourcePath => "MyApp.Strings.EnumResources";
 68    /// </code>
 69    ///
 70    /// Example 2: Separate image path for visual enum dropdown
 71    /// <code>
 72    /// [DynamicPathSource(nameof(ImagePath), ResourceUsage.Images)]
 73    /// public MyEnum IconChoice { get; set; }
 74    ///
 75    /// public string ImagePath => "MyApp.Images.Icons";
 76    /// </code>
 77    /// </example>
 78    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
 79    public class DynamicPathSourceAttribute : Attribute
 80#endif
 81    {
 82        /// <summary>
 83        /// Gets the name of the property that contains the resource path to use for this context.
 84        /// The referenced property should return a string representing a fully qualified resource class name
 85        /// (e.g., <c>"MyApp.Resources.MyStrings"</c>).
 86        /// </summary>
 87        public string PathPropertyName
 88        {
 2089            get;
 90#if NET8_0_OR_GREATER
 3291        } = pathPropertyName;
 92#else
 93        }
 94#endif
 95
 96        /// <summary>
 97        /// Indicates what type of resource this path is intended for (e.g., <see cref="ResourceUsage.Strings"/>,
 98        /// <see cref="ResourceUsage.Images"/>). Used to filter when multiple attributes are present.
 99        /// </summary>
 100        public ResourceUsage ResourceUsage
 101        {
 20102            get;
 103#if NET8_0_OR_GREATER
 32104        } = resourceUsage;
 105#else
 106        }
 107
 108        /// <summary>
 109        /// Initializes a new instance of the <see cref="DynamicPathSourceAttribute"/> class.
 110        /// </summary>
 111        /// <param name="pathPropertyName">
 112        /// The name of the property (on the same class) that returns a string resource path.
 113        /// </param>
 114        /// <param name="resourceUsage">
 115        /// The kind of resource this path will be used for. Defaults to <see cref="ResourceUsage.All"/>.
 116        /// </param>
 16117        public DynamicPathSourceAttribute(string pathPropertyName, ResourceUsage resourceUsage = ResourceUsage.All)
 8118        {
 16119            PathPropertyName = pathPropertyName;
 16120            ResourceUsage = resourceUsage;
 16121        }
 122#endif
 123
 124        /// <summary>
 125        /// Resolves the most appropriate <see cref="DynamicPathSourceAttribute"/> for the given context and usage.
 126        /// </summary>
 127        /// <param name="context">The context containing property and instance metadata.</param>
 128        /// <param name="resourceUsage">
 129        /// The intended type of resource (e.g., strings, images) to retrieve the matching attribute.
 130        /// </param>
 131        /// <returns>
 132        /// The best-matching <see cref="DynamicPathSourceAttribute"/>, or <c>null</c> if none found.
 133        /// </returns>
 134        /// <exception cref="ArgumentException">
 135        /// Thrown if <paramref name="resourceUsage"/> is <see cref="ResourceUsage.None"/>.
 136        /// </exception>
 137        public static DynamicPathSourceAttribute Get(ITypeDescriptorContext context, ResourceUsage resourceUsage = Resou
 64138        {
 72139            if (context?.Instance == null || context.PropertyDescriptor == null)
 20140                return null;
 141
 68142            if (resourceUsage == ResourceUsage.None)
 20143                throw new ArgumentException("resourceUsage must not be None", nameof(resourceUsage));
 144
 64145            var property = Support.Support.GetPropertyInfo(context);
 64146            var all = GetCustomAttributes(property, typeof(DynamicPathSourceAttribute))
 64147                               .OfType<DynamicPathSourceAttribute>();
 148
 149#if NET35
 150            return all.FirstOrDefault(a => (a.ResourceUsage & resourceUsage) != ResourceUsage.None);
 151#else
 84152            return all.FirstOrDefault(a => a.ResourceUsage.HasFlag(resourceUsage));
 153#endif
 60154        }
 155    }
 156}