Consider the following control (snipped for brevity):
public partial class ConfigurationManagerControl : UserControl
{
public Func<string, bool> CanEdit { get; set;}
public Func<string, bool> CanDelete { get; set; }
public Dictionary<string, string> Settings
{
get { return InnerSettings; }
set
{
InnerSettings = value;
BindData();
}
}
private Dictionary<string, string> InnerSettings;
private void OnListIndexChanged(object sender, EventArgs e)
{
this.EditButton.Enabled = false;
this.DeleteButton.Enabled = false;
var indices = this.List.SelectedIndices;
if (indices.Count != 1)
{
return;
}
var index = indices[0];
var item = this.List.Items[index];
if (this.CanEdit != null)
{
this.EditButton.Enabled = this.CanEdit(item.Text);
}
if (this.CanDelete != null)
{
this.DeleteButton.Enabled = this.CanDelete(item.Text);
}
}
}
There's more to this control, but suffice it to say that it allows a user to add, edit, and delete the entries in a Dictionary<string, string>. In order to determine whether or not it should allow the user to edit or delete the entries, it uses the delegate method properties, CanDelete and CanEdit, which are provided by the form or control that hosts it:
public class SetupWizard : Form
{
public SetupWizard()
{
InitializeComponent();
this.SettingManager.CanEdit = CanEditSetting;
this.SettingManager.CanDelete = CanDeleteSetting;
}
private static bool CanEditSetting(string item)
{
var lockedSettings = new[] { "LicenseHash", "ProductHash" };
return !lockedSettings.Contains(item.ToLower());
}
private static bool CanDeleteSetting(string item)
{
var lockedSettings = new[] {
"LicenseHash",
"ProductHash",
"UserName",
"CompanyName"
};
return !lockedSettings.Contains(item.ToLower());
}
}
I find that this design is both satisfactory and worrisome at the same time. On the one hand, it seems to solve the problem using the simplest solution that works (it certainly separates the concerns nicely). On the other hand, I have this nagging concern that I am using delegates improperly and should be using an event, instead (even though I do not need multiple listeners, and only need the caller to tell me if the item is editable).
And then, on the other other hand, there's the chance that there's a completely different design that I haven't even considered that might solve the problem in a vastly superior way.
So. Is this design technically correct, maintainable, and flexible? Or should I be doing something better?
I suggest the use of an interface with these two methods. That's a lot cleaner:
interface ICantThinkOfAGoodName
{
bool CanEdit(string item);
bool CanDelete(string item);
}
You could create something similar to the RelayCommand used in many MVVM frameworks:
public class RelayObject : ICantThinkOfAGoodName
{
public RelayObject() : this(null, null) {}
public RelayObject(Func<string, bool> canEdit, Func<string, bool> canDelete)
{
if(canEdit == null) canEdit = s => true;
if(canDelete == null) canDelete = s => true;
_canEdit = canEdit;
_canDelete = canDelete;
}
public bool CanEdit(string item)
{
return _canEdit(item);
}
public bool CanDelete(string item)
{
return _canDelete(item);
}
}
Use it like this:
public SetupWizard()
{
InitializeComponent();
this.SettingManager.PropertyName = new RelayObject(CanEditSetting,
CanDeleteSetting);
// or (all can be deleted)
this.SettingManager.PropertyName = new RelayObject(CanEditSetting, null);
// or (all can be edited)
this.SettingManager.PropertyName = new RelayObject(null, CanDeleteSetting);
// or (all can be edited and deleted)
this.SettingManager.PropertyName = new RelayObject();
}
BTW: I am using Property injection here, because it is a control. Normally, I would pass the ICantThinkOfAGoodName dependency in the constructor of the ConfigurationManagerControl.
It may be this is what #Daniel Hilgarth is suggesting when he says "use an interface" (n.b. - his answer now reflects a more general/flexible approach to implementing the interface). Instead of assigning delegates to your method directly, why not give the control a property, such as DataState or whatever you want to call it, using an interface that encapsulates the information you need, and leave it up to the owner to decide how to implement that.
interface IDataState
{
bool CanEdit(string item);
bool CanDelete(string item);
}
public partial class ConfigurationManagerControl : UserControl
{
public IDataState DataState {get;set;}
// your code checks DataState.CanEdit & DataState.CanDelete
}
public class SetupWizard : Form, IDataState
{
public SetupWizard()
{
InitializeComponent();
SettingManager.DataState =this;
}
public bool CanEdit(string item)
{
... implement directly or return from your private function
}
public bool CanDelete(string item)
{
}
}
But this gives you the flexibility to implement that interface any way you choose, with another object, etc. and it makes it easy to also just pass the owner itself (implementing the interface).
Related
I have a lot of duplicate code places:
if (claimSettingHistoryDto.NewClaimTypeName == claimSettingHistoryDto.OldClaimTypeName)
{
claimSettingHistoryDto.NewClaimTypeName = null;
claimSettingHistoryDto.OldClaimTypeName = null;
}
if (claimSettingHistoryDto.NewApplicantName == claimSettingHistoryDto.OldApplicantName)
{
claimSettingHistoryDto.NewApplicantName = null;
claimSettingHistoryDto.OldApplicantName = null;
}
if (claimSettingHistoryDto.NewDamageSparePartsTotalCostInsertion == claimSettingHistoryDto.OldDamageSparePartsTotalCostInsertion)
{
claimSettingHistoryDto.NewDamageSparePartsTotalCostInsertion = null;
claimSettingHistoryDto.OldDamageSparePartsTotalCostInsertion = null;
}
and so constantly for different classes of different fields
I wish I had a feature like this:
private void SetNull(object newData, object oldData)
{
if (newData == oldData)
{
newData = null;
oldData = null;
}
}
but of course I understand that this is not true, since I only change the local value inside the function. How do I change the class field?
There are multiple ways of doing that, with varying positions on the "good idea" to "bad idea" spectrum.
Fields as ref parameters (good idea)
(...) this is not true, since I only change the local value inside the function
You're wrong, because ref and out parameters allow you to change values non-locally.
If you have access to the actual fields, you can pass them as a ref parameter:
public class Dto
{
private string? _old;
private string? _new;
public string? Old => _old;
public string? New => _new;
public void Foo() {
SetNullIfEqual(ref _new, ref _old);
}
private static void SetNullIfEqual<T>(ref T? newData, ref T? oldData) where T: class
{
if (newData == oldData)
{
newData = null;
oldData = null;
}
}
}
More info on passing as reference here.
This won't work with properties, even if they have a default setter. Properties are not fields, they're methods in disguise. If you can't access the actual fields...
Properties as delegates (meh idea)
... having access to properties only you'd need to pass them as delegates like this:
public class Dto
{
public string? Old { get; set; }
public string? New { get; set; }
}
public class Outside
{
public void Foo(Dto dto) {
SetNullIfEqual(() => dto.New, () => dto.Old, v => dto.New = v, v => dto.Old = v);
}
private static void SetNullIfEqual<T>(
Func<T?> getNew,
Func<T?> getOld,
Action<T?> setNew,
Action<T?> setOld) where T: class
{
if (getNew() == getOld())
{
setNew(null);
setOld(null);
}
}
}
This is clunky though, you have to question how much space it'd actually save. An instance method working on fields as in the first suggestion works much better.
When you have reflection everything looks like a nail (probably bad idea)
You can also do this with reflection, which will remove all safety, give much worse performance, but the absolute most flexibility.
using System.Reflection;
public class Dto
{
public string? Old { get; set; }
public string? New { get; set; }
}
public class Outside
{
public void Foo(Dto dto) {
SetNullIfEqual(nameof(dto.New), nameof(dto.Old), dto);
}
private static void SetNullIfEqual<T>(
string newPropName,
string oldPropName,
T instance)
{
PropertyInfo newProp = typeof(T).GetProperty(newPropName);
PropertyInfo oldProp = typeof(T).GetProperty(oldPropName);
if (Equals(newProp.GetValue(instance), oldProp.GetValue(instance)))
{
newProp.SetValue(instance, null);
oldProp.SetValue(instance, null);
}
}
}
I removed all error handling for brevity.
Recommendation
I'd go with the fields-as-ref-parameters way. If the method in question lives outside of the type, so it can't have access to the fields (don't ever use public fields please), I'd just move it into the type. In your case it'd be a bunch of methods called SetClaimTypeName, SetApplicantName, etc.
I'm trying to plan a publish/subscribe implementation. I've tried several times but I get stuck cause I think either I don't understand the limitations of C# generics or I haven't gotten the correct way to do it.
I would like to keep a list of Events/Delegates that are associated with a type of object. So when the Method gets called it receives an object of correct type.
Furthermore I would like the way to use it to be like this:
Hub.Subscribe<MyMessageType>( MethodThatTakes<MyMessageType>);
Hub.Publish<MyMessageType>( new MyMessageType("Message"));
Hub.Subscribe<Vector3>( MethodThatTakes<Vector3>);
Hub.Publish<Vector3>( new Vector3(45,100,0));
My problem is I don't manage to get it to work this way. It becomes more complex to use but I'm thinking that the user shouldn't need to do more since more information is not needed.
So my question is if it's possible to make it work like this with generics or maybe I misunderstand something about how a pub sub could and should work?
Example of code to register a subscription
public static void Subscribe < T > (string title = "", CallbackMethod<T>) {
Subscriptions subs;
if (subscriptions.Any(sub => sub.Type == typeof (T) && sub.Title == title)) {
subs = subscriptions.First(sub => sub.Type == typeof (T) && sub.Title == title);
} else {
subs = new Subscriptions < T > (title);
}
}
class Subscriptions < T > {
internal Type Type;
List < CallbackMethodsWithParameter < T >> subscribers;
public Subscriptions() {
Type = T.GetType();
}
}
So here I am trying to have a subscriptions class store type of return and a list with methods to callback that takes an object of the same type.
It obviously doesn't work but that's where I am now and I'm not sure if it's even possible or a good way to do it.
Your sample registration code seems overly complex for what you are trying to achieve, which is simply registering an Action<T> and then publishing a message of T to all subscriptions.
However, this is not easily mapped for your use case since Action<in T> is contravariant and you need to store your handlers as Action<object> which would be a covariant interaction. That said, you can wrap the subscription handler and cast the incoming message.
public class Hub
{
private static object _subscriptionLock = new object();
private static ConcurrentDictionary<Type, ConcurrentBag<Action<object>>> _map =
new ConcurrentDictionary<Type, ConcurrentBag<Action<object>>>();
public void Subscribe<T>(Action<T> subscriptionHandler)
{
var entryExists = _map.TryGetValue(typeof(T), out var entry);
var wrappedHandler = Wrap(subscriptionHandler);
if (!entryExists)
{
entry = new ConcurrentBag<Action<object>>();
}
entry.Add(wrappedHandler);
_map[typeof(T)] = entry;
}
public void Publish<T>(T message)
{
var entryExists = _map.TryGetValue(typeof(T), out var entry);
if (!entryExists) return;
foreach (var handler in entry)
{
handler(message);
}
}
private Action<object> Wrap<T>(Action<T> input)
{
Action<object> f = (message) => input((T)message);
return f;
}
}
This allows the type of subscription and publish API that you are looking for:
void Main()
{
var hub = new Hub();
hub.Subscribe<TestMessageA>(HandlerOne);
hub.Subscribe<TestMessageA>(HandlerTwo);
hub.Subscribe<TestMessageB>(HandlerOne);
hub.Subscribe<TestMessageB>(HandlerTwo);
hub.Publish(new TestMessageA { Title = "hey there!" });
hub.Publish(new TestMessageB { Title = "hey there again!" });
}
public void HandlerOne(TestMessageA message)
{
Console.WriteLine($"{message.Title} in HandlerOne");
}
public void HandlerTwo(TestMessageA message)
{
Console.WriteLine($"{message.Title} in HandlerTwo");
}
public void HandlerOne(TestMessageB message)
{
Console.WriteLine($"{message.Title} in HandlerOne");
}
public void HandlerTwo(TestMessageB message)
{
Console.WriteLine($"{message.Title} in HandlerTwo");
}
public class TestMessageA
{
public int Id { get; set; }
public string Title { get; set; }
}
public class TestMessageB
{
public int Id { get; set; }
public string Title { get; set; }
}
which outputs:
hey there! in HandlerOne
hey there! in HandlerTwo
hey there again! in HandlerOne
hey there again! in HandlerTwo
I have class with two properties which are Lists, one of it contents int - that's IDs of objects from second List. I override setters and getters to save them agreeable with each other. But when I add some this to list they are not synchronized. How to make them synchronized?
Here is code
public class Item
{
private List<Operation> _operations = new List<Operation>();
private List<int> _operationsID = new List<int>();
public List<Operation> operations
{
get { return this._operations; }
set
{
this._operations = value;
if (value != null)
{
foreach (Operation oper in value)
{
this._operationsID.Add(oper.ID);
}
}
}
}
public List<int> operationsID
{
get { return this._operationsID; }
set
{
this._operationsID = value;
if (value != null)
{
foreach (int operID in value)
{
this._operations.Add(new Operation(operID));
}
}
}
}
}
Should I override List.Add if so, how it can me made?
It is a bit unclear what it is you are trying to do, but basically it seems like you need to encapsulate those lists so the user can't work on them directly (and get them out of sync). You do this by not exposing the lists to the user. Basically you are trying to keep the items contained to the user so whenever they work on your set of items, they would be forced to go through this class and the functions that class exposes. Your only issue then is to find out what to expose to the user and in what manner.
public class Item {
private List<Operation> _operations = new List<Operation>();
private List<int> _operationsID = new List<int>();
public void addOperation(Operation o) {
_operations.Add(o);
_operationsID.Add(getIdentifier(o));
}
public void removeOperation(Operation o) {
_operations.Remove(o);
_operationsID.Remove(getIdentifier(o));
}
public void clear() {
_operations.clear();
_operationsID.clear();
}
public void findOperationMatching(Foobar foo) {
//
}
private int getIdentifier(Operation id) {
//
}
}
You have to clear previous list content before calling Add method:
public List<Operation> operations
{
get { return this._operations; }
set
{
this._operations = value;
if (value != null)
{
this._operationsID.Clear();
foreach (Operation oper in value)
{
this._operationsID.Add(oper.ID);
}
}
else
{
this._operationsID = null;
}
}
}
But to be honest, I don't think it's a good idea to keep these things in two different lists. Why don't you use Dictionary<int, Operation>?
It's a bad idea to try to manage two versions of the truth. If it were me, I'd expose one List<Operation> that callers can Add/Remove, and a second IEnumerable<int> which simply exposes the ID's of the operations:
public List<Operation> Operations { get; set; }
public IEnumerable<int> OperationIDs
{
get
{
return Operations.Select(op => op.OperationID);
}
}
This way, callers can use the Operations list to do whatever they need to do (Add, Remove, Count, etc). The OperationIDs is now not a second property that people can work with; instead it only reflects information that is in the Operations property.
I am creating a project data pipeline and I need to return different types from a single class
in this class I have a number of Dictionaries that hold and separate the elements/content i want to load up but i need a way to return them with a single string... as i am not to familiar with these Type functions i am lost as to how to return the content properly
I need this in a separate class so i can do a XML serialization later
Here is what I have now
DataClass contents;
public T ReturnType<T>(string asset)
{
if(typeof(T) == typeof(int))
{
return contents.Integers[Asset];
}
if(typeof(T) == typeof(float))
{
return contents.Floats[Asset];
}
if(typeof(T) == typeof(double))
{
return contents.Doubles[Asset];
}
return default(T);
}
it will allow me to use a base Object class to parse the content but i dont want anything to get lost in transit so i am weary in using this method
my question is how to return one of the different objects of a certain types within the class that i am using for serialization with a function like that
If i wanted to use the previous function to grab content within the class eg
public Object someobject;
//button event handler to change the current object
//preferably this would be changed depending on the object i would be calling
//but this should do for showing how it is supposed to work
public void ChangeCurrentObject(event e)
{
someobject = (Object)ReturnType<Object>("23rdObject");
}
it sends a string to the function called 'ReturnType' and returns an object ie(int, float,etc) within there own respective dictionary
The generics in this case will only help you not to write diferent method for every asset type. You can also use this aproach to make it more modular.
static class Assets
{
public interface IAssetHandler<out T>
{
T GetAsset(string name);
}
private static readonly Dictionary<Type,object> _handlers=new Dictionary<Type, object>();
public static T GetAsset<T>(string name)
{
object assetHandler;
if(!_handlers.TryGetValue(typeof(T),out assetHandler))
{
throw new Exception("No handler for that type of asset");
}
return (assetHandler as IAssetHandler<T>).GetAsset(name);
}
public static void RegisterAssetHandler<T>(IAssetHandler<T> handler)
{
_handlers[typeof (T)] = handler;
}
}
public class IntAssetsHandler:Assets.IAssetHandler<int>
{
#region Implementation of IAssetHandler<out int>
public int GetAsset(string name)
{
return 0;
}
#endregion
}
static void Main(string[] args)
{
Assets.RegisterAssetHandler(new IntAssetsHandler());
Console.WriteLine(Assets.GetAsset<int>("test"));
}
You could use external class, set the properties types as you wish, then use it in your function.
public class MultipleOpjects
{
public List<string> ObjectOne { get; set; }
public List<object> ObjectTwo { get; set; }
public object ObjectThree { get; set; }
}
public MultipleOpjects GetAnything()
{
MultipleOpjects Vrble = new MultipleOpjects();
Vrble.ObjectOne = SomeThing1;
Vrble.ObjectTwo = SomeThing2;
Vrble.ObjectThree = SomeThing3;
return Vrble;
}
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 :)
Related question.
I would suggest creating something that parallels the ObservableCollection<T> where appropriate. Specifically, I would suggest following the existing techniques for notification of change of collection. Something like:
class MyObservableCollection<T>
: INotifyPropertyChanging, // Already exists
INotifyPropertyChanged, // Already exists
INotifyCollectionChanging, // You'll have to create this (based on INotifyCollectionChanged)
INotifyCollectionChanged // Already exists
{ }
This will follow established patterns so that clients are already familiar with the exposed interfaces-- three of the interfaces already exist. The use of existing interfaces will also allow more proper interaction with other already existing .NET technologies, such as WPF (which binds against the INotifyPropertyChanged and INotifyCollectionChanged interfaces.)
I would expect the INotifyCollectionChanged interface to look something like:
public interface INotifyCollectionChanged
{
event CollectionChangingEventHandler CollectionChanging;
}
public delegate void CollectionChangingEventHandler(
object source,
CollectionChangingEventArgs e
);
/// <remarks> This should parallel CollectionChangedEventArgs. the same
/// information should be passed to that event. </remarks>
public class CollectionChangingEventArgs : EventArgs
{
// appropriate .ctors here
public NotifyCollectionChangedAction Action { get; private set; }
public IList NewItems { get; private set; }
public int NewStartingIndex { get; private set; }
public IList OldItems { get; private set; }
public int OldStartingIndex { get; private set; }
}
If you wish to add cancellation support, simply add a writable bool Cancel property to CollectionChangingEventArgs that the collection will read to determine whether to execute the change that's about to occur.
I suppose this falls under your Option 2. This is the way to go because, to interoperate properly with other .net technologies that monitor changing collections, you're going to have to implement it anyway for INotifyCollectionChanged. This will definitely follow the policy of "Least Surprise" in your interface.
I would recomend seperate events. It seems more clear to me.
EDIT:
You might want to cosider a before and after event such as Inserting,Inserted or as the VB guys have it BeforeInsert, AfterInsert. This will give the user more flexability.
Have a look at this link, maybe that is what you are looking for, a Generic List based object that acts as a List but with built-in events such as BeforeItemAdded, ItemAdded, BeforeItemRemoved, ItemRemoved and ItemsCleared.
Hope this helps, Tom. :)
Actually, you will be surprised how easily you can create a collection like that.
Take a look at System.Collections.ObjectModel.Collection<T>. That is a class which is intended to be used for such things. It has a few virtual methods (one for every operation) which you can override and control very well.
I would recommend Option 1, since it is more clear and straightforward.
Here is an example which you can use for such purposes:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
namespace TestGround
{
public class MyCollection<T> : Collection<T>
{
public class ListChangeEventArgs : EventArgs
{
public IEnumerable<T> ItemsInvolved { get; set;}
public int? Index { get; set;}
}
public delegate void ListEventHandler(object sender, ListChangeEventArgs e);
public event ListEventHandler Inserting;
public event ListEventHandler Setting;
public event ListEventHandler Clearing;
public event ListEventHandler Removing;
public MyCollection() : base() { }
public MyCollection(IList<T> innerList) : base(innerList) { }
protected override void ClearItems()
{
Clearing(this, new ListChangeEventArgs()
{
Index = null,
ItemsInvolved = this.ToArray(),
});
base.ClearItems();
}
protected override void InsertItem(int index, T item)
{
Inserting(this, new ListChangeEventArgs()
{
Index = index,
ItemsInvolved = new T[] { item },
});
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
Removing(this, new ListChangeEventArgs()
{
Index = index,
ItemsInvolved = new T[] { this[index] },
});
base.RemoveItem(index);
}
protected override void SetItem(int index, T item)
{
Setting(this, new ListChangeEventArgs()
{
Index = index,
ItemsInvolved = new T[] { item },
});
base.SetItem(index, item);
}
}
}
You could also modify the ListChangeEventArgs to have a bool property with the name "Cancel", and control wheter to do the change or not in the collection.
The after events could also be useful, if you need such functionality.
Of course, you won't have to use all events of every collections, or if it is really necessary, there may be other ways to solve the problem depending on why do you need this functionality.
EDIT:
If you really only want to validate the items and set their Parent property to an entity instance, you can actually write a collection which does exactly that, or something that generalizes the problem in another way. You could pass it a delegate which validates the item, and and another which tells it what to do when an item is added or removed.
For example, you can achieve this using the Action delegate.
You could consume it this way:
class Order : Entity
{
public Order()
{
OrderItems = new MyCollection2<OrderItem>(
//Validation action
item => item.Name != null && item.Name.Length < 20,
//Add action
item => item.Parent = this,
//Remove action
item => item.Parent = null
);
}
...
}
The major benefit of this approach is that you don't have to bother with event handlers or delegates, beacuse all that you need can be written using lambda expressions, however if you need something more advanced, you can always use a real delegate instead of them.
This is an example of the collection:
public class MyCollection2<T> : Collection<T>
{
public Func<T, bool> Validate { get; protected set; }
public Action<T> AddAction { get; protected set; }
public Action<T> RemoveAction { get; protected set; }
public MyCollection2(Func<T, bool> validate, Action<T> add, Action<T> remove)
: base()
{
Validate = Validate;
AddAction = add;
RemoveAction = remove;
}
protected override void ClearItems()
{
foreach (var item in this)
{
RemoveAction(item);
}
base.ClearItems();
}
protected override void InsertItem(int index, T item)
{
if (Validate(item))
{
AddAction(item);
base.InsertItem(index, item);
}
}
protected override void RemoveItem(int index)
{
RemoveAction(this[index]);
base.RemoveItem(index);
}
protected override void SetItem(int index, T item)
{
if (Validate(item))
{
RemoveAction(this[index]);
AddAction(item);
base.SetItem(index, item);
}
}
}
For such purposes, I think this is the cleanest way to go.