Although BindingList<T>
and ObservableCollection<T>
provide mechanisms to detect list changes, they don't support mechanisms to detect/intercept changes before they happen.
I'm writing a couple of interfaces to support this, but I want to canvas your opinion.
Option 1: Lists raise events for each type of action
Here, consumers might write code like this:
public class Order : Entity
{
public Order()
{
this.OrderItems = new List<OrderItem>();
this.OrderItems.InsertingItem += new ListChangingEventHandler<OrderItem>(OrderItems_InsertingItem);
this.OrderItems.SettingItem += new ListChangingEventHandler<OrderItem>(OrderItems_SettingItem);
this.OrderItems.RemovingItem += new ListChangingEventHandler<OrderItem>(OrderItems_RemovingItem);
}
virtual public List<OrderItem> OrderItems { get; internal set; }
void OrderItems_InsertingItem(object sender, IOperationEventArgs<OrderItem> e)
{
if (!validationPasses)
{
e.Cancel = true;
return;
}
e.Item.Parent = this;
}
void OrderItems_SettingItem(object sender, IOperationEventArgs<OrderItem> e)
{
if (!validationPasses)
{
e.Cancel = true;
return;
}
e.Item.Parent = this;
}
void OrderItems_RemovingItem(object sender, IOperationEventArgs<OrderItem> e)
{
if (!validationPasses)
{
e.Cancel = true;
return;
}
e.Item.Parent = null;
}
}
Option 2: Lists raise a single event, and the action is determined from the event args
Here, consumers might write code like this:
public class Order : Entity
{
public Order()
{
this.OrderItems = new List<OrderItem>();
this.OrderItems.ListChanging += new ListChangingEventHandler<OrderItem>(OrderItems_ListChanging);
}
virtual public List<OrderItem> OrderItems { get; internal set; }
void OrderItems_ListChanging(object sender, IOperationEventArgs<OrderItem> e)
{
switch (e.Action)
{
case ListChangingType.Inserting:
case ListChangingType.Setting:
if (validationPasses)
{
e.Item.Parent = this;
}
else
{
e.Cancel = true;
}
break;
case ListChangingType.Removing:
if (validationPasses)
{
e.Item.Parent = null;
}
else
{
e.Cancel = true;
}
break;
}
}
}
Background: I'm writing a set of general purpose interfaces/classes that represent the core components of DDD, and I'm making the source code available (hence the need to create friendly interfaces).
This question is about making the interface as cohesive as possible, so that consumers can derive and implement their own collections without losing the core semantics.
PS: Please don't suggest using AddXYZ()
and RemoveXYZ()
methods for each list, because I've already discounted that idea.
PPS: I must include developers using .NET 2.0 :)