Saturday 4 February 2012

ENRICH ENUMS WITH ATTRIBUTES AND RETRIEVE VALUES GENERICALLY



Working on repayment frequency enumeration and its annual occurence,  I came up with the idea of implementing field attributes. Then found a good way to obtain the value of annual occurences which is embedded to the attribute. I implemented an enumeration extension to achieve this.

This is a neat and tidy way to enrich enumerations with custom attributes and get the values of these attributes by an enumeration extension.

The enumeration class:

namespace MyApplication.Domain.Enumerations
{
  public enum RepaymentFrequency
  {
     [AnnualOccurence(12)] 
     [DaysImplied(30)]
     Monthly, 

     [AnnualOccurence(52)] 
     [DaysImplied(7)]
     Weekly,
        ....
        ....
}


The custom attribute class for AnnualOccurence (it will be pretty much the same for DaysImplied):

using System;
 
namespace MyApplication.Domain.Enumerations
{
    [AttributeUsage(AttributeTargets.Field)]
    public class AnnualOccurence : Attribute
    {
        public static readonly short Unassigned = -1;
 
        public AnnualOccurence()
        {
            _numberOfAnnualRepayments = Unassigned;
        }
 
        private short _numberOfAnnualRepayments;
        public short NumberOfAnnualRepayments
        {
            get { return _numberOfAnnualRepayments;}
        }
 
        public AnnualOccurence(short numberOfOccurences)
        {
            _numberOfAnnualRepayments = numberOfOccurences;
        }
 
        public override string ToString()
        {
            return "Annual Occurence = " + _numberOfAnnualRepayments.ToString();
        }
    }
}
Now, there is a good way to get the values of such attributes from an 'enumeration instance', by implementing the following extension:

using System;
using System.Linq;
 
namespace HomeStart.LoanCalculators.Domain.Enumerations
{
    public static class EnumExtensions
    {
        public static Expected GetAttributeValue<T, Expected>
                      (this Enum enumeration, Func<T, Expected> expression)
            where T : Attribute
        {
         T attribute = enumeration.GetType().GetMember(enumeration.ToString())[0]
                            .GetCustomAttributes(typeof(T), false)
                               .Cast<T>().SingleOrDefault();
 
            if (attribute == null)
                return default(Expected);
 
            return expression(attribute);
        }
    }
}
 
with the following usage:  
 
RepaymentFrequency repaymentFrequency = repaymentFrequency.Weekly;
... 
var numberOfAnnualRepayments = 
                 repaymentFrequency.GetAttributeValue<AnnualOccurence, short>
                                            (x => x.NumberOfAnnualRepayments);
var numberOfDaysImplied =  
                 repaymentFrequency.GetAttributeValue<DaysImplied, short> 
                                            (x => x.NumberOfDaysImplied);
...


where 52 will be assigned to numberOfAnnualRepayments
and 7 will be assigned to numberOfDaysImplied in this case.


No comments:

Post a Comment