lucamilan
1/3/2012 - 3:46 PM

DOMAIN MODEL with BUSINESS EVENTS (original idea Daniel Cazzulino)

DOMAIN MODEL with BUSINESS EVENTS (original idea Daniel Cazzulino)

    /// <summary>
    /// Domain Event
    /// </summary>
    public class CustomerChangeLevel : EventArgs {
        public decimal Amount { get; set; }
    }

    /// <summary>
    /// Simple Enum
    /// </summary>    
    public enum CustomerLevel { Bronze, Silver, Gold };

    /// <summary>
    /// Domain Entity
    /// </summary>
    public class Customer : DomainObject {

        public Customer() {

            //  SETUP EVENT
            Handles<CustomerChangeLevel>(this.OnChangingLevel);
 
        }
     
        //   OBJECT STATE
        public CustomerLevel Level { get; private set; }
        public decimal Amount { get; private set; }
        
        /// <summary>
        /// Business Method
        /// </summary>
        /// <param name="amount"></param>
        public void SetAmountOfPurchase(Decimal amount)
        {
            //  CHECK CONSTRAINT
            if (amount < 0) throw new ApplicationException("Invalid amount");

            Apply(new CustomerChangeLevel() { Amount=amount });

            //  RAISE EVENTS INTERNALS
            //ChangeLevel(this, args);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="args"></param>
        private void OnChangingLevel(CustomerChangeLevel args)
        {
            //  CHANGE DOMAIN OBJECT STATE
            Amount = args.Amount;
            
            //  APPLY SPECIFIC DOMAIN RULE
            if (Amount > 100) Level = CustomerLevel.Gold;
            if (Amount < 100) Level = CustomerLevel.Silver;
            if (Amount <= 0) Level = CustomerLevel.Bronze;            
        }

    }

    /// <summary>
    /// Base Class for DOMAIN OBJECT
    /// </summary>
    public class DomainObject
    {
        private List<EventArgs> events = new List<EventArgs>();

        protected void Apply<TEvent>(TEvent args)
            where TEvent : EventArgs
        {
            this.events.Add(args);

            var handler = default(Action<EventArgs>);
            if (this.handlers.TryGetValue(args.GetType(), out handler))
                handler(args);
        }

        private Dictionary<Type, Action<EventArgs>> handlers = new Dictionary<Type, Action<EventArgs>>();

        protected void Handles<TEvent>(Action<TEvent> handler)
            where TEvent : EventArgs
        {
            this.handlers.Add(typeof(TEvent), @event => handler((TEvent)@event));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public IEnumerable<EventArgs> GetEvents()
        {
            return this.events.AsReadOnly();
        }
    }