c# list property Add method extra action - c#

i have a list property like that
protected IList<System.Windows.Media.Color> colors;
public IList<System.Windows.Media.Color> Colors
{
get { return colors; }
set { colors = value; }
}
and i have a function
protected void updateBuffers()
which needs to be called each time a property user change the property, for example
Colors.Add(...)
...
Colors.Clear(...)
is there an elegent simple way to do that?

You could create a new object that created additional properties, using the List as a base class:
public class CustomList<T> : List<T>
{
public new void Add(T item) {
base.Add(item);
this.UpdateBuffers();
}
}
The 'new' keyword is required to completely overwrite the existing implementation of Add, which isn't marked as virtual in the base class.
Thanks to Hans Passant and LarsTech for their feedback in the comments.

You cannot with a plain list.
You can however create your own class implementing IList<T> or inherit from Collection<T>.
Or you can use an ObservableCollection<T> or any built-in class implementing INotifyCollectionChanged
see MSDN for documentation.
Moreover, ObservableCollection will allow you to use your collection in bindings if you are using them for populating UI in WPF or Windows 8 applications.

Related

When should I use inheritance over utility classes?

I am working on a project that uses Canvas objects. I would like to add a few functionalities to manipulate them.
Until now, I was adding them in a CanvasUtils class but now I realize that I could actually create a CustomCanvas class that would inherit from Canvas and implement the new functionalities.
I can feel the second way is more intuitive but I am not sure whether it is the best option or not.
For example, if I keep adding new methods to a CustomCanvas class it is going to become huge at some point whereas I can easily break a utils class into several ones.
Also a Utils class sounds more independent and extendable to me. For example, if I wanted to extend some of the functionalities to Panel objects (Canvas inherits from Panel), I think it would be easier to do it with a Utils class as you just have to change the Canvas references to Panel.
My questions are:
what are the advantages and flaws of each method and
when should I use one over another?
If you are adding new functionality, then you should extend the class. You'll be able to add your own state, as well as methods to interact with them. However, you won't be able to add this functionality to existing objects.
If you are simply writing shortcuts that use existing functionality, then you can use Extension Methods to add functions without needing to extend the class. For example...
public static class PanelExtensions
{
public static void DoSomething(this Panel panel)
{
panel.SomePanelMethod();
panel.SomeOtherPanelMethod();
}
}
And then to use this...
Panel myPanel = new Panel();
myPanel.DoSomething();
The advantage of this approach is that the methods are available to existing panels, and they will be inherited too (so your Canvas objects will receive these methods too).
Note than in order to use extension methods, you need to have a using statement at the top of your file referencing the namespace in which they are defined.
It depends on what you are trying to achieve and what do you need to implement new functionality:
If you have stateless methods that do not need any additional information associated with object, then you can either continue to use Util methods or turn them into Extension methods that will give you both the inheritance-like feel of use and loose coupling of the Util class:
public static class CanvasExtensions
{
public static void TransformElements(this Canvas canvas,
Action<CanvasElement> transform)
{
...
foreach(var elem in canvas.Children)
{
transform(elem);
}
...
}
}
If you need to associate some piece of info with the object you operate on, then:
you can either inherit the class if the object's behaviour shall be deeply affected by additional functionality (like when other standard methods can negate new functionality) to allow base function overriding:
public class DeeplyAffectedCanvas : Canvas
{
private IDictionary<CanvasElement, Action> m_dictionary;
public void SpecialTransform(CanvasElement elem, Action transform) { }
public override void Resize()
{
// Resize, for example, have to take into account
// the special operation
}
}
or create a wrapper, that exposes the original object (Panel) when the additional behaviour doesn't affect the wrapped object much:
public class Wrapper<T>
{
public Wrapper(T wrapped)
{
this.Wrapped = wrapped;
}
public T Wrapped { get; private set; }
public implicit operator T (Wrapper<T> wrapper)
{
return wrapper.Wrapped;
}
}
public class WrappedCanvas : Wrapper<Canvas>
{
private Object data;
public void SafeTransform(...);
}

Do a check when List.Add method is called

I have a composite property called Items of type List to an order class. On the GUI the user fills out some fields like Name, Description, Price, Quantity, etc... and then clicks the Add Item button which of course adds the item to the order's list of items. What I'd like to do is create a method that checks the item's IsComplete property which does a check to ensure the required properties are set so that way someone can't just call order.Items.Add(item) if it isn't complete. If it's not I'd like an exception to be thrown if the item's IsComplete property returns false... What would be an easy way to go about this?
This can be achieved by sub-classing List<T> into a derived class, and then overriding the Add method, like so.
public class MyItemCollection : List<MyItem>
{
public override void Add(MyItem item)
{
if (item.IsComplete)
{
base.Add(item);
}
else
{
throw new InvalidOperationException("Unable to add an incomplete item");
}
}
}
Your order class would then have the property MyItemCollection rather than List<T>, like so:
public class Order
{
public MyItemCollection Items { get; set; }
}
You can also use ObservableCollection<T>: http://msdn.microsoft.com/en-us/library/ms668604.aspx
It implements INotifyCollectionChanged: http://msdn.microsoft.com/en-us/library/System.Collections.Specialized.INotifyCollectionChanged.aspx
Since the method Add(T) is not virtual you can't override, it.
ObservableCollection allow to throw an event when an element was added but not to undo this add.
You can implement the interface IList<T> with a List<T> storred internaly and add the desired verification in the method Add(T item) before calling the _list.Add(item) like in the exemple below :
public class MyItemCollection : IList<MyItem>
{
private List<MyItem> _list;
public MyItemCollection()
{
_list = new List<MyItem>();
}
public void Add(MyItem item)
{
if (item.IsComplete)
{
_list.Add(item);
}
else
{
throw new InvalidOperationException("Unable to add an incomplete item");
}
}
//Then you have to implement all the IList interface members...
}
The only problem with this solution is that it require to write a lot of boilerplate code.
If only one class is responsible of the manipulation of your List, you can also decide to implement a method AddToMyItemCollection(MyItem item) in the responsible class. It is even a good practive as it's respect the GRASP pattern protected variation (Instance.getC() is preferable to Instance.getA().getB().getC())

PropertyGrid - Collection Edition / Wrapper

I have a complex kind of property I want to edit in a PropertyGrid.
interface IInterface{}
abstract class Base : IInterface{}
class A : Base{}
class B : Base{}
These class represent what can be stored in the property (The content of these class does not matter).
// The Property to be displayed in the PropertyGrid
class Property
{
List<Base> MyListOfObjects {get;set;}
}
I managed to create a derived class of System.ComponentModel.Design.CollectionEditor which allows me to add different kind of datas, using [Editor(typeof(MyCollectionEditor), typeof(UITypeEditor))] attribute in the collection property.
class MyCollectionEditor : CollectionEditor
{
public MyCollectionEditor(Type type) : base(type)
{
}
#region Overrides of CollectionEditor
protected override Type[] CreateNewItemTypes()
{
base.CreateNewItemTypes();
// [EDIT assembly, see below]
var types = (from t in Assembly.GetAssembly(typeof(IInterface)).GetTypes()
where t.GetInterfaces().Contains(typeof (IInterface)) && !t.IsAbstract
select t).ToArray();
return types;
}
protected override Type CreateCollectionItemType()
{
return typeof(A); // 1st problem
}
}
First Problem: The only solution I found to be able to edit the objects is to give a concrete child class type in CreateCollectionItemType(). Why? How to avoid that?
Second Problem: I now want to use a wrapper to give this property to the propertyGrid item. Instead of having the property attributes ([Category("General")] for instance) in the model, I want to put them in a wrapper.
It works fine for everything but the collection.
Here is how I did it:
class abstract WrapperBase<T>
{
T WrappedObject{get;set;}
}
class PropertyWrapper:WrapperBase<Property>
{
List<Base> MyListOfObjects
{
get{return WrappedObject.MyListOfObjects;}
set{WrappedObject.MyListOfObjects=value;}
}
}
With this, the collection editor won't let me add objects to this Collection, and the dropdown that was available to add a specific kind of object is gone.
Any idea? Thanks in advance!
[EDIT]
The second part of the problem is solved: Since the wrapper is located in another assembly, I was not looking in the right place for the implementations of IInterface.
CreateNewItemTypes is good. in CreateCollectionItemType return the base type. i think that should work.

C#'s ListBox doesn't see my overrided Sort() method

I'm trying to override Sort() method in my custom control. When my control contains ListBox and then I override Sort() method, everything works.
But when I want my ListBox (1) to be extended by another ListBox (2), that contains Sort() method, and then add that ListBox (1) to my UserControl, then it sorts too, but isn't using my Sort() method (seems like it doesn't see my Sort(), just normal Sort() from ListBox class).
My ListBox (2) contains code:
//...
public class MyListBox: ListBox
{
public MyListBox
{
this.Sorted = true;
}
// more methods
override protected void Sort()
{
// sorting code
}
}
//...
And my custom control looks like:
//...
public partial class MyControl: UserControl
{
public MyControl()
{
InitializeComponent(); // method in MyControl.Designer.cs (myListBox1 is declared in that class)
}
// more methods
public ListBox.ObjectCollection Item //that's because I want my control to behavior like ListBox instead of creating void AddItem(Object) method, etc...
{
get { return myListBox1.Items; }
}
}
so I think everything should work, but it doesn't... Any ideas?
If you call your Sort, it could be necessary to cast your ListBox to your custom ListBox type (if it is in the base type) to use your specified Sort method.
((MyListBox)myList).Sort();
you must use your overriden ListBox with its correct type, I mean use it as MyListBox and not as ListBox. Don't be afraid that you need to implement all the other methods, you're overriding an existing class and not an interface. you can use all the needed base methods.
If I understand this correctly myListBox1 is of type ListBox not of type MyListBox which is why your Sort isn't being called.

Limiting access to a public setter to specific objects (C#)

I'm trying to create a class (in C#) that serves as an environment for my application.
I'm trying to make the class dynamic, and send it as a parameter to entities in my application. The problem is, that I want to be able to change the properties of this environment class (public setters), but at the same time I want the classes that receive the environment to be unable to use these setters.
I can't seem to find a good way to phrase my question (which I figure is a part of the reason I can't find anything like this on Google or msdn), but to put shortly, I want to create a class with setters that are public only for some of my objects and not for all.
I'm currently amusing the following idea:
Avoiding the public setters all together, and expose the private fields using event registration.
The class will register to events in a new third object (sent as a parameter to the constructor). The methods that will be registered by the environment are not much more then setters, and so triggering these events will "allow access" to the private fields.
I'd love some ideas (seeing as I feel that mine isn't all that great), or better yet some patterns I could make use of.
Thanks in advance
Isn't "internal" sufficient for what you need?
And you could move the setters into an interface as explicit implementation. Then they are hidden from the public interface and only accessible if you cast to the interface.
And if you want to make really sure that nobody else can call it you can add some parameter to these functions where you expect a certain token object which you only give to trusted classes.
void SetX(int value, object token)
{
if(token!=correctToken)
throw new ArgumentException("wrong token");
x=value;
}
You could create a proxy, and send that proxy to your entity classes.
class MyClass
{
public int MyProperty { get; set; }
}
class MyProxyClass
{
public MyProxyClass(MyClass myClass)
{
_myClass = myClass;
}
private MyClass _myClass;
public int MyProperty
{
get { return _myClass.MyProperty; }
}
}
You could try using Friend assemblies. That will allow only the assemblies you specify to have access to your privates (snicker).
Maybe i understood something not quite well, but i think Jon had a quite similar problem which he described here. Maybe this can help you.
How about
class Callee
{
public void SetX(TypeOfCaller caller, int value)
{
}
}
class TypeOfCaller
{
public void Do()
{
Callee instance;
//..
instance.SetX(this, 5);
}
}
Doing so; you can also use Visual Studio' Find References feature! In case you want multiple types of caller; you can either opt for class hierarchy or can simply have required overloads
Why not return clones of your protected objects instead of the actual objects? Solves the problem without adding any more complexity.
public class MyService
{
private List<MyObject> _protectedObjects = new List<MyObject>();
public MyObject GetItem(int id)
{
return (MyObject)_protectedObjects.First(i => i.Id == id).Clone();
}
}
public class MyObject : ICloneable
{
//[...]
public object Clone()
{
return MemberwiseClone();
}
}

Categories

Resources