In my current project I need to be able to have both editable and read-only versions of classes. So that when the classes are displayed in a List or PropertGrid the user is not able to edit objects they should not be allowed to.
To do this I'm following the design pattern shown in the diagram below. I start with a read-only interface (IWidget
), and then create an edtiable class which implements this interface (Widget
). Next I create a read-only class (ReadOnlyWidget
) which simply wraps the mutable class and also implements the read only interface.
I'm following this pattern for a number of different unrelated types. But now I want to add a search function to my program, which can generate results that include any variety of types including both mutable and immutable versions. So now I want to add another set of interfaces (IItem
, IMutableItem
) that define properties which apply to all types. So IItem
defines a set of generic immutable properties, and IMutableItem
defines the same properties but editable. In the end a search will return a collection of IItems
, which can then later be cast to more specific types if needed.
Yet, I'm not sure if I'm setting up the relationships to IMutable
and IItem
correctly. Right now I have each of the interfaces (IWidget
, IDooHickey
) inheriting from IItem
, and then the mutable classes (Widget
, DooHickey
) in addition also implement IMutableItem
.
Alternatively, I was also thinking I could then set IMutableItem
to inherit from IItem
, which would hide its read-only properties with new properties that have both get and set accessors. Then the mutable classes would implement IMutableItem
, and the read-only classes would implement IItem
.
I'd appreciate any suggestions or criticisms regarding any of this.
Class Diagram
Code
public interface IItem
{
string ItemName { get; }
}
public interface IMutableItem
{
string ItemName { get; set; }
}
public interface IWidget:IItem
{
void Wiggle();
}
public abstract class Widget : IWidget, IMutableItem
{
public string ItemName
{
get;
set;
}
public void Wiggle()
{
//wiggle a little
}
}
public class ReadOnlyWidget : IWidget
{
private Widget _widget;
public ReadOnlyWidget(Widget widget)
{
this._widget = widget;
}
public void Wiggle()
{
_widget.Wiggle();
}
public string ItemName
{
get {return _widget.ItemName; }
}
}
public interface IDoohickey:IItem
{
void DoSomthing();
}
public abstract class Doohickey : IDoohickey, IMutableItem
{
public void DoSomthing()
{
//work it, work it
}
public string ItemName
{
get;
set;
}
}
public class ReadOnlyDoohickey : IDoohickey
{
private Doohickey _doohicky;
public ReadOnlyDoohickey(Doohickey doohicky)
{
this._doohicky = doohicky;
}
public string ItemName
{
get { return _doohicky.ItemName; }
}
public void DoSomthing()
{
this._doohicky.DoSomthing();
}
}