Reputation: 110
I am inheriting some System.Windows.Forms-Control
(about 10 pieces).
Each of them gets some custom extensions, but most of the extension will be the same for each control.
Actually I have to code the same functionality separate for each of them. This is a lot of copy+paste and difficult to maintain.
class MyButton : Button
{
//this is only in MyButton
public int ButtonProperty { get; set; }
public object Property1 { get; set; }
public object Property2 { get; set; }
public void MakeInvisible()
{
this.Visible = false;
}
}
class MyLabel : Label
{
//this is only in MyLabel
public bool LabelProperty { get; set; }
//same propertys and methods as in MyButton
public object Property1 { get; set; }//copy+paste
public object Property2 { get; set; }//copy+paste
public void MakeInvisible()//copy+paste
{
this.Visible = false;
}
}
What I am searching for is a way to extend all of the derived classes like you can do with an interface
or extension method. But I also want to have properties and access the base class (Control
)
This is what I am dreaming about:
class MyButton : Button, MyExtension
{
//this is only in MyButton
public int ButtonProperty { get; set; }
}
class MyLabel : Label, MyExtension
{
//this is only in MyLabel
public bool LabelProperty { get; set; }
}
//Extension for all classes inherited from Control
class MyExtension : Control
{
public object Property1 { get; set; }
public object Property2 { get; set; }
public void MakeInvisible()
{
this.Visible = false;
}
}
Upvotes: 3
Views: 1993
Reputation: 32780
If you need to leverage protected
methods and properties of the extended controls then you are out of luck, there is no way to acheive what you want without extensive copy and paste.
If you only need access to public methods and properties, then how about something along the following lines:
public interface IControlExtension
{
Foo MyProperty { get; set; }
Blah MyMethod();
}
public abstract class ControlExtension: IControlExtension
{
private Control owner;
private ControlExtension(Control owner)
{
Debug.Assert(owner != null);
this.owner = owner;
}
public static IControlExtension GetControlExtension(Control c)
{
if (c is Button ||
c is Label)
{
return new SimpleControlExtension(c);
}
if (c is Panel || ...
{
return new ContainerControlExtension(c);
}
}
public abstract Foo MyProperty { get; set; }
public abstract Blah MyMethod();
private class SimpleControlExtension: ControlExtension
{
public override Foo MyProperty { .... }
public override Blah MyMethod { ....
}
private class ContainerControlExtension: ControlExtension
{
public override Foo MyProperty { .... }
public override Blah MyMethod { .... }
}
}
Now, in all your extended controls, the copy and paste code is minimum:
public class MyButton : Button
{
public MyButton()
{
....
var controlExtension = ControlExtension.GetControlExtension(this);
}
public IControlExtension { get { return controlExtension; } }
}
Upvotes: 0
Reputation: 35720
idea:
create a new type for common properties
give each control a property of that type
implementation:
// TypeConverter required for PropertyGrid in design mode
// found here: http://stackoverflow.com/a/6107953/1506454
[TypeConverter(typeof(ExpandableObjectConverter))]
public class MyExtension
{
// need reference to control to work with in methods
private Control _c;
public MyExtension(Control c)
{
_c = c;
}
// can be inhereted for different controls, if necessary
public string Property1 { get; set; }
public string Property2 { get; set; }
public void MakeInvisible()
{
_c.Visible = false;
}
}
// common interface of extended controls
public interface IExtended
{
MyExtension Extra { get; }
}
// MyButton implements extended interface
public class MyButton : Button, IExtended
{
public MyButton()
{
// create extended properties for button
Extra = new MyExtension(this);
}
// for designer serialization support
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public MyExtension Extra { get; private set; }
//this is only in MyButton
public int ButtonProperty { get; set; }
}
// common extension methods
public static class MyControlHelper
{
public static void MakeInvisible<TControl>(this TControl control) where TControl : Control, IExtended
{
control.Extra.MakeInvisible();
}
public static void Rename<TControl>(this TControl control) where TControl : Control, IExtended
{
control.Text = control.Extra.Property1;
}
}
Upvotes: 2
Reputation: 32296
Instead of inheriting from the Button
and Label
you could use composition.
class MyExtension
{
protected Control control;
public MyExtension(Control control)
{
this.control = control;
}
public object Property1 { get; set; }
public object Property2 { get; set; }
public void MakeInvisible()
{
this.control.Visible = false;
}
}
class MyButton : MyExtension
{
public MyButton(Button button):base(button){}
public int ButtonProperty { get; set; }
}
class MyLabel : Label
{
public MyButton(Label label):base(label){}
public bool LabelProperty { get; set; }
}
You could even make MyExtension
abstract
if you don't want any instances of it created. The main difference here is that you'll have to create a Button
or Label
to pass in and you might want to expose them as properties of your MyButton
and MyLabel
so you can get at their properties.
Upvotes: 0
Reputation: 20764
You can use extension methods for this purpose
public static class ControlHelper
{
public static void MakeInvisible(this Control c)
{
c.Visible = false;
}
}
and use it like this
var mb = new MyButton();
mb.MakeInvisible();
var ml = new MyLabel();
ml.MakeInvisible();
By using this approach you can generate extension methods for base classes and use it in derived classes.
Upvotes: 0
Reputation: 6537
C# doesn't support multi inheritance. You should try something like this - MyButton : MyExtension;
and MyExtension : Button
. In this case you will extend MyButton class with MyExtension and Button classes.
Upvotes: 0