Explicitly call interface methods from a winforms base class - c#

I have a winforms baseform that contain calls to certain methods that need to be implemented in derived forms. I want to ensure that my derived forms do indeed implement those methods with as much compile time support as possible. We all know the problem of not being able to define a winforms class as abstract if you want to be able to use the designer (see this question).
I created an Interface that contains the method signatures that need to be implemented in a derived form. I then call the Interface methods directly from the base class like such:
((IMyFormInterface)this).SomeInterfaceMethod();
(Note that my base class does not inherit IMyFormInterface. If it did, then derived classes wouldn't be forced to implement it.)
And then I inherit from the Interface in my derived form (which the compiler forces me to implement):
public partial class TestForm : BaseForm, IMyFormInterface
The only thing I (or other users) have to remember is to inherit IMyFormInterface.
Is it acceptable to call interface methods directly like this? My goal in all of this is to be able to get as close as possible to ensuring derived forms implement these "abstract" form methods at compile time, not run time.

That's one way to work around the designer restriction. Another would be to use the designer to build a UserControl, and then let your form base class be abstract and instantiate the control docked to the full client area.
If you use this approach, I'd assert (this is IMyFormInterface) in your constructor to catch that error as early as possible.

I had the same problem with a base control.
Because Designer does not like abstract base control classes I refactored the abstract methods to virtual methods that throw a NotImplementedException.
I don't know which way is the best.

Related

One base class for both forms and user controls

I have a Form with several methods for input validation. I want this validation logic to be shared between several Forms and UserControls. What should be the type of the base class? It cannot be Form since it will also be used for UserControls and it cannot be UserControl since it will also be used for Forms.
My instinct tells me that a solution might involve generics, but I am not sure.
Note: By "validation logic" I refer to the implementation, so interfaces are not a solution.
Edit (to make the question a bit clearer): I do have a separate class for actually validating the input. However, I use an ErrorProvider to indicate the user that the input is invalid. My InputValidator class calls a method inside the Form/UserControl that shows the error to the user, using the ErrorProvider. I just do not want to copy-paste this method for every Form/UserControl.
You cannot create a base class that handles both Forms and UserControls. However, you could create a base class for your Forms and another one for your UserControls.
In addition, create an interface that both base classes implement and that publishes the members that you need to use in the validator.
By this approach, the amount of code that is duplicated is at least reduced to two locations. Please note, that there are some OOP practices that will not work in the context of Windows Forms (e.g. abstract classes) because the designer introduces some limitations.
Original answer:
In this case, the best option is to move the validation logic to a separate class of its own. You can use this new class from both the Forms and the UserControls.
If you need to refer to the Form or UserControl during validation, you can use a parameter of type ContainerControl. This class is the base class of both Form and UserControl. This way, you can create shared logic that works for all classes that inherit from ContainerControl.
Use composition instead of inheritance. See: Composition over inheritance (wikipedia).
Your forms must inherit from Form or from another form which inherits from Form. Your user controls must inherit from UserControl or from another user control which inherits from UserControl. You cannot change this and therefore you cannot supply your own base class for both of them.
Instead, implement your validation logic in a separate class, and use it inside your forms and user controls.
public partial class MyForm : Form
{
private readonly MyValidation _validation;
public Myform()
{
InitializeComponent();
_validation = new MyValidation(errorProvider1);
}
//TODO: use _validation instead of inherited validation logic.
}
I cannot give you more details on how to implement this exactly, as I don't know what your validation is.
First thing is first - I think Olivier's answer is a very good one, and I would advise you to use it.
However, while you can't change the base classes of Form and UserControl, there is still a way to write your method only once using an interface and an extension method - and this is what I wanted to show in my answer here.
The interface:
internal interface IValidatable
{
ErrorProvider ErrorProvider {get;}
}
The extension class:
internal static class IValidatableExtensions
{
internal void ShowValidationResult(this IValidatable self, ValidationResult result)
{
// Here you can use self.ErrorProvider to show your results
}
}
Now you can have your forms and user controls implement the IVilidatable interface, and in the validation class simply call the ShowValidationResult method.
Again, I would simply send the validation instance a reference to the errorProvider as Olivier has demonstrated in his answer, but this technique might be useful in other cases, so I thought I better add an answer myself.

Can abstract classes have implementation in c#?

The compiler doesn't seem to mind it so far but I just wanted to double check whether I'm setting myself up for failure in any way by implementing certain methods in my abstract class.
An abstract class usually has one or more abstract method. So yes it can have some method implemented. The goal is to force the user to implement these methods to have an object working. Sometimes abstract classes are used to provide a 'base' implementation of some interfaces, leaving the final user to specify just the key methods. You can also have an abstract class without any abstract method: in this case you are asserting you must derive from that class in order to use it.
It's common to have some implementation in abstract classes.
If there is no implementation at all, consider using an interface instead of an abstract class.
Perfectly fine to implement some methods and leave others abstract.
If all methods had to be abstract, you might as well use an interface for it.
Yes. abstract class cannot be instantiated (you have to instantiate a class that inherits from your abstract class), but it can contains implementations.
it's fine and allowed, an abstract class has at least a member (method/property) not implemented so it cannot be instantiated.
an interface is also called pure abstract class which means it's 100% abstract, so does not allow you to specify any implementation.
keep in mind that there are lots of articles and opinions about never deriving a concrete class from another concrete class but only from abstract ones... at least this was the trend in C++ up to some years ago, then I moved to the C# side, started working more and had no time to keep reading those nice articles... :)

internal abstract methods. Why would anyone have them?

I was doing some code review today and came across an old code written by some developer. It goes something like this
public abstract class BaseControl
{
internal abstract void DoSomething();
}
If you have a derived class within the same assembly, it would work
public class DerivedControl : BaseControl
{
internal override void DoSomething()
{
}
}
But deriving the base class in a different assembly would give compile time error
DerivedControl does not implement inherited abstract member 'BaseControl.DoSomething()
That got me thinking. Why would anyone declare a method as internal abstract ?
The original programmer wanted to make a derived control available to client code. But prevent the client from inheriting and messing with the virtual method. That's not a bad idea, it is usually easy to break a base class by overriding a method and doing something like forgetting to call the base class method.
One obvious case is where the method receives or returns an internal type. For example, the core methods of the WPF Transform classes process some internal interop types, which WPF doesn't expose as part of its public API. Because the signature includes internal types, the method can't be public or protected. And yet clearly it's appropriate (necessary!) for the various Transform classes to work polymorphically. Therefore the base methods in Transform/GeneralTransform have to be internal.
Another, but related reason is to prevent external derivation. After all, the WPF architects could have exposed a "safe" version of the internal interop types in a protected abstract method, so that users could create their own Transform classes. They didn't because they didn't want to have to cope with the ways that people might use that capability, e.g. creating non-affine transforms. Allowing external derivation would have made the job of other classes in WPF hugely more complex, so the architects decided to allow only "approved" derived classes by making an abstract method internal.
My initial reaction was that there is no good reason, if you want to prevent external inheritance then you should mark the class internal. But that means that the class is totally hidden to other assemblies.
I suppose this method prevents external inheritance while retaining visibility.
By defining a method as internal abstract you want to make sure that only the class in the same assembly can have its implementation for your method.
now if you distribute a dll of it this will avoid the client to inherit and mesup the implementation.

internal constructor

Yesterday I thought it would be nice to implement my own Trigger in a WPF app. I created a class MyTrigger which inherited TriggerBase. TriggerBase is a public abstract class. So inheritance isn't a problem. But the constructors inside this class are marked internal. The compiler throws an error because the is no valid constructor. Why does anyone create a public class but marks the constructors as internal?
If you want the class to be visible, but only allow it to be subclassed within your own assembly. The subclasses may have public constuctors themselves - or they may be accessed with a factory.
I can't comment on whether that's a good design decision for TriggerBase in WPF, but it's at least reasonable in some situations.
One reason that I could think of is that the actual creation of new instances would be handled by another public class in the same assembly. This would force that you create the instance through this other class - possibly some sort of a factory pattern implementation.
It's public because it's used as a base class for the triggers that ship with WPF (Trigger, MultiTrigger, EventTrigger, DataTrigger etc). It it wasn't public then you wouldn't be able to flag these classes as public.
The constructors are internal because they don't intend for you to use it yourself. I'd guess you're suppose to derive from one of the classes mentioned above.

C# Apply Interface to a Form Class

How can I apply an Interface to a form class
partial class Form1 : Form, InterfaceA
Is this correct?
Basically I would like to implement an Interface on a form.
How To ....
A Form is just a class (that subclasses System.Windows.Forms.Form), so yes - standard syntax is fine, as you have it.
Edit: As to your partial class part of the question, no, you need only declare that you implement the interface once. From MSDN...
If any of the parts are declared abstract, then the entire type is considered abstract. If any of the parts are declared sealed, then the entire type is considered sealed. If any of the parts declare a base type, then the entire type inherits that class.
Remember, there's no magic in forms or partial classes. C#/.Net is one of the few Microsoft projects that's wizardry free - it really does tend to behave the way you think it should.
Yes - a form is just a class at the end of the day
When working with partial classes in C#, either:
any declaration with the ':' operator must specify exactly the same baseclass and interfaces
specifying baseclass and interfaces on one of the declarations will suffice
To make life easier for yourself, add the interface specs in only one place (without checking I suspect this is in the designer class part by default when working with the WinForms designer).

Categories