示例#1
0
            public Terms New(Waypoint pickup, Waypoint dropoff, string otherTerms)
            {
                Precondition.MustNotBeNull(pickup, nameof(pickup));
                Precondition.MustNotBeNull(dropoff, nameof(dropoff));

                if (pickup.Time.End <= _clock.Now)
                {
                    throw new ArgumentOutOfRangeException(
                              "pickup.Time.End must be in the future, " +
                              $"but it was {pickup.Time.End}",
                              nameof(pickup));
                }

                if (dropoff.Time.End <= _clock.Now)
                {
                    throw new ArgumentOutOfRangeException(
                              "dropoff.Time.End must be in the future, " +
                              $"but it was {dropoff.Time.End}",
                              nameof(dropoff));
                }

                if (pickup.Time.End > dropoff.Time.End)
                {
                    throw new ArgumentException(
                              "pickup.Time.End must be earlier than dropoff.Time.End",
                              nameof(dropoff));
                }

                return(new Terms
                {
                    Pickup = pickup,
                    Dropoff = dropoff,
                    OtherTerms = otherTerms ?? string.Empty,
                });
            }
示例#2
0
        public Waypoint(Location place, TimeRange time)
        {
            Precondition.MustNotBeNull(place, nameof(place));
            Precondition.MustNotBeNull(time, nameof(time));

            _place = place;
            _time  = time;
        }
示例#3
0
            private void PriceMustBeNonNegative(Money price)
            {
                Precondition.MustNotBeNull(price, nameof(price));

                if (price.IsNegative)
                {
                    throw new NegativePriceProhibited(price);
                }
            }
示例#4
0
            private void BiddingMustBeAllowedNow(ReverseAuctionAggregate reverseAuction)
            {
                Precondition.MustNotBeNull(reverseAuction, nameof(reverseAuction));

                if (!reverseAuction.BiddingAllowed.Includes(_clock.Now))
                {
                    throw new BiddingNotAllowedNow(reverseAuction, _clock);
                }
            }
示例#5
0
            public Bid.BidAggregate PlaceBid(
                ReverseAuctionAggregate reverseAuction,
                TimeRange pickupTime,
                TimeRange dropoffTime,
                Money price)
            {
                Precondition.MustNotBeNull(reverseAuction, nameof(reverseAuction));

                // RULE: We'd like to delegate validation and precondition
                // checking to Factorys.  That keeps the Aggregate code
                // clean and simple...
                // but we need to enforce a relationship between the Auction
                // and the new Bid.

                BiddingMustBeAllowedNow(reverseAuction);
                BidMustConformToAuctionTime(
                    reverseAuction.Root.BuyerTerms.Pickup,
                    nameof(pickupTime),
                    pickupTime);
                BidMustConformToAuctionTime(
                    reverseAuction.Root.BuyerTerms.Dropoff,
                    nameof(dropoffTime),
                    dropoffTime);
                PriceMustBeNonNegative(price);

                var bid = _bidFactory.New(
                    reverseAuction.Id,
                    pickupTime,
                    dropoffTime,
                    price);

                // TODO: According to IDDD, we'd publish a "created" event
                // here.  I need to fit this into the context of our work
                // to wrap DB transactions around business interactions.
                // OTOH, there may be no conflict if the domain event
                // publisher is flexible enough that in test the event is
                // published immediately but in production the event is
                // only published when the transaction is committed.
                // However, if the consistency boundary IS the aggregate,
                // it may not be reasonable to wait.

                var aggregate = new Bid.BidAggregate(bid);

                _interAggregateEventBus.Publish(
                    new Bid.Event.BidCreated(aggregate));

                return(aggregate);
            }
示例#6
0
            private void BidMustConformToAuctionTime(
                Waypoint auctionWaypoint,
                string argumentName,
                TimeRange bidTime)
            {
                Precondition.MustNotBeNull(auctionWaypoint, nameof(auctionWaypoint));
                Precondition.MustNotBeNull(argumentName, nameof(argumentName));
                Precondition.MustNotBeNull(bidTime, nameof(bidTime));

                if (!auctionWaypoint.Time.Includes(bidTime))
                {
                    throw new BidTimeDisagreesWithAuctionTime(
                              auctionWaypoint,
                              argumentName,
                              bidTime);
                }
            }
示例#7
0
            public Bid New(
                int reverseAuctionId,
                TimeRange pickupTime,
                TimeRange dropoffTime,
                Money price)
            {
                Precondition.MustNotBeNull(pickupTime, nameof(pickupTime));
                Precondition.MustNotBeNull(dropoffTime, nameof(dropoffTime));
                Precondition.MustNotBeNull(price, nameof(price));

                return(new Bid
                {
                    ReverseAuctionId = reverseAuctionId,
                    PickupTime = pickupTime,
                    DropoffTime = dropoffTime,
                    Price = price,
                });
            }
示例#8
0
        private static string ValidatedCurrencyCode(string currencyCode)
        {
            Precondition.MustNotBeNull(currencyCode, nameof(currencyCode));

            currencyCode = currencyCode.ToUpper(); // ignore case

            if (!Iso4217CurrencyCodePattern.IsMatch(currencyCode))
            {
                throw new InvalidCurrencyCodeFormat(nameof(currencyCode));
            }

            if (!Iso4217CurrencyCodes.Contains(currencyCode))
            {
                throw new UnknownCurrencyCode(currencyCode, nameof(currencyCode));
            }

            return(currencyCode);
        }
示例#9
0
            public ReverseAuction New(Terms buyerTerms, TimeRange biddingAllowed)
            {
                Precondition.MustNotBeNull(buyerTerms, nameof(buyerTerms));
                Precondition.MustNotBeNull(biddingAllowed, nameof(biddingAllowed));

                if (biddingAllowed.End < _clock.Now)
                {
                    throw new ArgumentOutOfRangeException(
                              "biddingAllowed TimeRange must end in the future, " +
                              $"but it was {biddingAllowed}");
                }

                // PERK: Using a "constructor service" eliminates the compiler
                // complaining about virtual method calls in the constructor.
                return(new ReverseAuction
                {
                    BuyerTerms = buyerTerms,
                    BiddingAllowed = biddingAllowed,
                });
            }
示例#10
0
 /// <summary>
 /// DomainEvents have <c>internal</c> constructors because they should
 /// only be constructed within the Domain project.  Nothing outside
 /// the Domain should ever publish or create one.
 /// </summary>
 internal ReverseAuctionEvent(ReverseAuctionAggregate created)
 {
     Precondition.MustNotBeNull(created, nameof(created));
     Id = created.Id;
 }
示例#11
0
 /// <summary>
 /// DomainEvents have <c>internal</c> constructors because they should
 /// only be constructed within the Domain project.  Nothing outside
 /// the Domain should ever publish or create one.
 /// </summary>
 internal BidEvent(BidAggregate created)
 {
     Precondition.MustNotBeNull(created, nameof(created));
     Id = created.Id;
 }