LinkAdd#
A new dependency between two tasks, added to a live project through SchedulingChanges.Links.Add. It has the same properties as LinkData, except that Id is nullable. Build one with an object initializer; Source and Target are required.
Declaration#
namespace Plen;
public sealed class LinkAdd : IDeepCloneable<LinkAdd>
LinkAdd has no constructor that sets the required properties, so new LinkAdd() without Source and Target doesn't compile.
Properties#
| Property | Type | Default | Description |
|---|---|---|---|
Id |
Id? |
null |
Id of the new link. null makes Apply generate one. |
Source |
Id |
required | Id of the predecessor task. |
Target |
Id |
required | Id of the successor task. |
LinkType |
LinkType |
LinkType.Fs |
Which end of Source drives which end of Target. |
Lag |
double |
0.0 |
Working time between the two ends, in LagUnit. Must be finite. |
LagUnit |
TimeUnit? |
null |
Unit of Lag. null uses SchedulingConfig.DurationUnit. |
Source, Target, LinkType, Lag and LagUnit mean the same as on LinkData, including what happens when an endpoint names no task. A string, int or double converts to Id implicitly.
Id#
public Id? Id { get; set; }
A non-null id stores the link under that id. It must not repeat the id of a link already in the project.
null makes Project.Apply pick the first free id of the form $generated_link_1, $generated_link_2, and so on. The generated id is listed in ApplyReport.Effects.GeneratedLinks, so you can store it for later updates or removals.
Methods#
DeepClone#
public LinkAdd DeepClone()
Returns a copy with the same property values.
ToString#
public override string ToString()
Returns a readable rendering of every property, for logging.
LinkAdd doesn't override Equals; two instances compare by reference.
Errors#
A LinkAdd is one operation, named links.add[i]. It's rejected, and listed as a RejectedOperation in ApplyReport.Rejected instead of applied, when:
Idis non-null and a link with that id already exists:duplicate link idLagisNaNor infinite:lag must be finite
A rejection isn't thrown. Apply reports it and keeps going.
An endpoint that names no task, or names an unscheduled task, doesn't reject the operation; see ChangeEffects.DroppedLinks.
A LinkAdd can reuse the id of a link removed in the same change set, because link removals run before link adds; see operation order.
Example#
Link task 1 to task 2 in a solved project, and read back the generated link id:
using Plen;
var start = Moment.FromYmdHm(2026, 4, 6, 8, 0)
?? throw new InvalidOperationException("invalid date");
var data = new ProjectData
{
Tasks =
[
new TaskData(1) { StartDate = start, Duration = 2.0 },
new TaskData(2) { StartDate = start, Duration = 3.0 },
],
};
var project = new Project();
var options = new SolveOptions();
project.Solve(data, options);
var changes = new SchedulingChanges();
changes.Links.Add.Add(new LinkAdd { Source = 1, Target = 2, LinkType = LinkType.Fs });
var report = project.Apply(changes);
Console.WriteLine($"new link ids: {string.Join(", ", report.Effects.GeneratedLinks)}");
var result = project.Solve(null, options);
foreach (var update in result.Updates)
Console.WriteLine($"task {update.Id}: {update.StartDate} .. {update.EndDate}");
Related#
LinkData- the same link in project dataLinkUpdate- edits an existing linkSchedulingChanges- the change set that carries the addApplyReport- generated ids and rejections- Editing a project - the full edit cycle