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, }); }
public Waypoint(Location place, TimeRange time) { Precondition.MustNotBeNull(place, nameof(place)); Precondition.MustNotBeNull(time, nameof(time)); _place = place; _time = time; }
private void PriceMustBeNonNegative(Money price) { Precondition.MustNotBeNull(price, nameof(price)); if (price.IsNegative) { throw new NegativePriceProhibited(price); } }
private void BiddingMustBeAllowedNow(ReverseAuctionAggregate reverseAuction) { Precondition.MustNotBeNull(reverseAuction, nameof(reverseAuction)); if (!reverseAuction.BiddingAllowed.Includes(_clock.Now)) { throw new BiddingNotAllowedNow(reverseAuction, _clock); } }
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); }
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); } }
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, }); }
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); }
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, }); }
/// <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; }
/// <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; }