Attributes are wonderful for decorating your Enums with additional markup and meta data. However, looking up attributes via reflection is not always a fast operation in terms of performance. Additionally, no one likes typing that code over and over again.
Well not to worry, just use the following extension methods to help cache your Enum attribute look ups, and increase your application's performance! But how much faster is this? Good question...
Iterations | Average Elapsed Ticks | Difference | |
---|---|---|---|
No Cache | With Cache | ||
2 | 1182.00 | 3934.00 | 4x Slower |
10 | 20.10 | 7.10 | 3x Faster |
100 | 13.07 | 1.37 | 10x Faster |
1,000 | 13.27 | 1.40 | 10x Faster |
10,000 | 13.56 | 1.45 | 10x Faster |
100,000 | 13.02 | 1.33 | 10x Faster |
Enum Extensions Code
public static class EnumExtensions
{
private static readonly
ConcurrentDictionary<Tuple<bool, Type, Type, Enum>, Attribute>
AttributeMap =
new ConcurrentDictionary<Tuple<bool, Type, Type, Enum>, Attribute>();
/// <summary>
/// Gets the specified attribute from an enum via a cache.
/// </summary>
public static T GetAttribute<T>(this Enum value, bool inherit = true)
where T : Attribute
{
var attrType = typeof(T);
var valueType = value.GetType();
var key = new Tuple<bool, Type, Type, Enum>(
inherit, attrType, valueType, value);
var attribute = AttributeMap.GetOrAdd(key, GetAttribute);
return attribute as T;
}
private static Attribute GetAttribute(Tuple<bool, Type, Type, Enum> key)
{
var valueString = key.Item4.ToString();
var field = key.Item3.GetField(valueString);
return Attribute.GetCustomAttribute(field, key.Item2, key.Item1);
}
/// <summary>
/// Returns a description of the enum if provided via a Description
/// attribute. If not provided, the normal name is returned
/// </summary>
public static string Description(this Enum value)
{
return value.Description<DescriptionAttribute>();
}
/// <summary>
/// Returns a description of the enum if provided via an extended
/// Description attribute. If not provided, the normal name is returned
/// </summary>
public static string Description<T>(this Enum value)
where T : DescriptionAttribute
{
var attribute = value.GetAttribute<T>();
return attribute != null
? attribute.Description
: value.ToString();
}
}
Unit Tests
public class EnumExtensionsTests
{
public class TestAttribute : Attribute
{
public string Message { get; set; }
public TestAttribute(string message) { Message = message; }
}
public enum TestEnum
{
[Description("Hello world!")]
HelloWorld = 1,
[Test("Goodnight, moon?")]
GoodnightMoon = 2
}
[Fact]
public void DescriptionTest()
{
var helloWorld = TestEnum.HelloWorld.Description();
Assert.Equal("Hello world!", helloWorld);
var goodnightMoon = TestEnum.GoodnightMoon.Description();
Assert.Equal("GoodnightMoon", goodnightMoon);
}
[Fact]
public void GetAttributeTest()
{
var helloWorld = TestEnum.HelloWorld.GetAttribute<TestAttribute>();
Assert.Null(helloWorld);
var goodnightMoon = TestEnum.GoodnightMoon.GetAttribute<TestAttribute>();
Assert.Equal("Goodnight, moon?", goodnightMoon.Message);
}
}
Enjoy,
Tom
It’s important that you submit a quality essay because a poor one can jeopardize your academic career. This is why many students turn to a essay writing service to help them finish their essays.essays
ReplyDeleteThe information was usefull but not cleared
ReplyDelete