private void Invariant() { Contract.Invariant(ServicePipDependencies.IsValid); Contract.Invariant(FinalizationPipIds.IsValid); Contract.Invariant( !ShutdownPipId.IsValid || Kind == ServicePipKind.Service, "'ShutdownProcessPipId' may only be specified when the pip is a 'Service'"); Contract.Invariant( !FinalizationPipIds.Any() || Kind == ServicePipKind.Service, "'FinalizationPipids' may only be specified when the pip is a 'Service'"); // NOTE: The constraint below is not required by the engine, but is enforced here just to // help users out, and catch builds that are *likely* to be errors. If and when we // encounter a case where a user will want to schedule a shutdown command from their // own build specs (e.g., so that they can have some other pips depend on it), we can // just lift this constraint. Contract.Invariant( Kind != ServicePipKind.Service || ShutdownPipId.IsValid, "A pip that is a 'Service' must have the 'ShutdownProcessPipId' specified"); Contract.Invariant( ServicePipDependencies.All(pipId => pipId.IsValid), "'ServicePipDependencies' must not contain invalid PipIds"); Contract.Invariant( Kind != ServicePipKind.ServiceClient || ServicePipDependencies.Any(), "A pip that is a 'ServiceClient' must have some 'ServicePipDependencies'"); Contract.Invariant( !ServicePipDependencies.Any() || Kind == ServicePipKind.ServiceClient, "'ServicePipDependencies' may only be specified for a pip that is either a 'ServiceClient'"); }
/// <nodoc /> public ServiceInfo( ServicePipKind kind, ReadOnlyArray <PipId> servicePipDependencies = default(ReadOnlyArray <PipId>), PipId shutdownProcessPipId = default(PipId), ReadOnlyArray <PipId> finalizationPipIds = default(ReadOnlyArray <PipId>), StringId tagToTrack = default(StringId), StringId displayNameForTag = default(StringId)) { Kind = kind; ServicePipDependencies = servicePipDependencies.IsValid ? servicePipDependencies : ReadOnlyArray <PipId> .Empty; ShutdownPipId = shutdownProcessPipId; FinalizationPipIds = finalizationPipIds.IsValid ? finalizationPipIds : ReadOnlyArray <PipId> .Empty; TagToTrack = tagToTrack; DisplayNameForTrackableTag = displayNameForTag; Contract.Assert(ServicePipDependencies.IsValid); Contract.Assert(FinalizationPipIds.IsValid); Contract.Assert( !ShutdownPipId.IsValid || Kind == ServicePipKind.Service, "'ShutdownProcessPipId' may only be specified when the pip is a 'Service'"); Contract.Assert( !FinalizationPipIds.Any() || Kind == ServicePipKind.Service, "'FinalizationPipids' may only be specified when the pip is a 'Service'"); // NOTE: The constraint below is not required by the engine, but is enforced here just to // help users out, and catch builds that are *likely* to be errors. If and when we // encounter a case where a user will want to schedule a shutdown command from their // own build specs (e.g., so that they can have some other pips depend on it), we can // just lift this constraint. Contract.Assert( Kind != ServicePipKind.Service || ShutdownPipId.IsValid, "A pip that is a 'Service' must have the 'ShutdownProcessPipId' specified"); Contract.Assert( ServicePipDependencies.All(pipId => pipId.IsValid), "'ServicePipDependencies' must not contain invalid PipIds"); Contract.Assert( Kind != ServicePipKind.ServiceClient || ServicePipDependencies.Any(), "A pip that is a 'ServiceClient' must have some 'ServicePipDependencies'"); Contract.Assert( !ServicePipDependencies.Any() || Kind == ServicePipKind.ServiceClient, "'ServicePipDependencies' may only be specified for a pip that is either a 'ServiceClient'"); Contract.Assert( TagToTrack.IsValid == DisplayNameForTrackableTag.IsValid, "Tag and its display name must be specified at the same time"); Contract.Assert( !TagToTrack.IsValid || Kind == ServicePipKind.Service, "'TagToTrack' may only be specified when the pip is a 'Service'"); }