Skip to content

Instantly share code, notes, and snippets.

@Archomeda
Created January 23, 2019 11:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Archomeda/293c5c5a5edeceaba810a076a9a35f09 to your computer and use it in GitHub Desktop.
Save Archomeda/293c5c5a5edeceaba810a076a9a35f09 to your computer and use it in GitHub Desktop.
Class to bind attribute properties to enums (C#)
using System;
using System.Collections.Generic;
using System.Linq;
namespace ClassLibrary1
{
/// <summary>
/// A class for binding properties to enums, implemented as custom attributes.
/// </summary>
/// <typeparam name="TEnum">The enum type.</typeparam>
/// <typeparam name="TAttribute">The attribute type.</typeparam>
public abstract class EnumWithProperties<TEnum, TAttribute>
where TEnum : Enum
where TAttribute : Attribute
{
private static Dictionary<TEnum, TAttribute> cache = new Dictionary<TEnum, TAttribute>();
/// <summary>
/// Initializes a new instance of the <see cref="EnumWithProperties{TEnum, TAttribute}"/> class.
/// </summary>
/// <param name="enum">The enum.</param>
/// <exception cref="ArgumentException">Thrown if the provided enum value is unsupported.</exception>
protected EnumWithProperties(TEnum @enum)
{
Value = @enum;
if (!cache.TryGetValue(@enum, out var attribute))
throw new ArgumentException($"Unsupported enum value '{@enum}' for enum type '{typeof(TEnum).Name}'", nameof(@enum));
AttributeData = attribute;
}
/// <summary>
/// Gets the enum value.
/// </summary>
public TEnum Value { get; }
/// <summary>
/// Gets the attribute data.
/// </summary>
protected TAttribute AttributeData { get; }
static EnumWithProperties()
{
// Use reflection to dynamically get the enum attributes.
// This uses reflection, which is slow, so we need to cache them to speed things up.
var enums = Enum.GetValues(typeof(TEnum)).Cast<TEnum>();
foreach (var @enum in enums)
{
var member = typeof(TEnum).GetMember(typeof(TEnum).GetEnumName(@enum));
var attribute = member.FirstOrDefault()?
.GetCustomAttributes(typeof(TAttribute), false)
.FirstOrDefault() as TAttribute;
if (attribute != null)
cache[@enum] = attribute;
}
}
}
}
using System;
namespace ClassLibrary1
{
public enum EExample
{
[Example("Id1")]
Value1 = 1,
[Example("Id2")]
Value2 = 2,
[Example("Id3")]
Value3 = 3,
[Example("Id4")]
Value4 = 4
// Add new values here
}
public class Example : EnumWithProperties<EExample, ExampleAttribute>
{
public Example(EExample @enum) : base(@enum)
{
Id = AttributeData.Id;
}
public string Id { get; }
}
public class ExampleAttribute : Attribute
{
public ExampleAttribute(string id)
{
Id = id;
}
public string Id { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment