Pre_ and Post_ Events - c#

I am creating an class library in C++/CLI to be used with C#, and as part of that library, i am offering up a customised version of System.Windows.Forms.Form and System.Windows.Forms.Control as System.Windows.Forms.HAForm and System.Windows.Forms.HAControl. I want to override OnPaint in a way that allows me to have OnPaint_Pre, OnPaint_Post AND OnPaint as i need to handle certain things every time before any painting is done, and handle some things AFTER painted has completed.
While this alone is simple enough, with this being a class in a library that is to be inherited from, i do not want to simply create an OnPaint in my class as this will be overwritten by the end developers OnPaint, and even if they do call base.OnPaint, the events will be fired out of order. i.e. OnPaint_Pre, my OnPaint, OnPaint_Post, sub classes OnPaint.
How would i create a class that inserts two events, one before the existing event, and one after?

I hope you don't mind me using C# syntax instead of C++/CLI...
You can make the HAForm/HAControl OnPaint override sealed, and create a new virtual function that derived classes can override. You can even use an intermediate class to give the new virtual function the same name:
public class HAControlBase : Control
{
protected virtual void OnPaintPre(PaintEventArgs e) { }
protected virtual void OnPaintPost(PaintEventArgs e) { }
internal virtual void OnPaintImpl(PaintEventArgs e) {
base.OnPaint(e);
}
protected sealed override OnPaint(PaintEventArgs e) {
OnPaintPre(e);
OnPaintImpl(e);
OnPaintPost(e);
}
}
public class HAControl : HAControlBase
{
internal sealed override void OnPaintImpl(PaintEventArgs e) {
OnPaint(e);
}
protected new virtual void OnPaint(PaintEventArgs e) {
base.OnPaintImpl(e);
}
}
Now, even if a derived class overrides HAControl.OnPaint, it will only be called after HAControlBase.OnPaint has already finished with OnPaintPre, there is no way to override Control.OnPaint (because that override is sealed) to call anything before OnPaintPre.

Related

Adjust accessibility of derived methods when changed on parent

I decided to change access modifier of a method which is overridden in multiple classes. So now I need to adjust accessibility modifier in all of them.
I assumed that is so common operation that Visual Studio (2019) should be able to do it automatically for me, but I couldn't find a way to do it.
Did I miss something or "manually" is the only way to go?
Not available out of the box.
Find and replace could mostly work:
Find in project/solution: public override void MyMethod(
Replace with: 'protected override void MyMethod('
Roslynator is a free/open source Visual Studio extension that has a large amount of extra refactorings, a.o. change accessibility.
For example, this changes this:
class Base
{
protected virtual void Method() { }
}
class Derived : Base
{
protected override void Method() { }
}
to this:
class Base
{
public virtual void Method() { }
}
class Derived : Base
{
public override void Method() { }
}
You could click on the x references tag above the class name to get a list of derived classes:

How to perform a cross-hierarchy call in C#

I am working on a simple GUI framework, and I faced a problem calling protected virtual methods.
Here is the IKeyboardInputListenerService interface of service I use to receive keyboard events and the Control class that represents a base for all my GUI controls. The internal method is the one being refactored.
public interface IKeyboardInputListenerService
{
event EventHandler<KeyboardEventArgs> KeyPressed;
}
public abstract class Control
{
public IKeyboardInputListenerService KeyboardInputListenerService { get; }
protected Control(IKeyboardInputListenerService keyboardInputListenerService) =>
KeyboardInputListenerService = keyboardInputListenerService;
public event EventHandler<KeyboardEventArgs> KeyPressed;
/* protected */ internal virtual void OnKeyPressed(object sender, KeyboardEventArgs args)
{
if (enabled && visible && focused && !args.Suppressed)
{
KeyPressed?.Invoke(sender, args);
args.Suppressed = true;
}
}
public void Activate() =>
KeyboardInputListenerService.KeyPressed += new EventHandler<KeyboardEventArgs>(OnKeyPressed);
}
I also created a ContainerControl class that is supposed to contain child controls(like the Panel or GroupBox in Windows Forms) and that overrides the virtual method:
public abstract class ContainerControl : Control
{
private readonly ObservableCollection<Control> controls;
protected ContainerControl(IKeyboardInputListenerService keyboardInputListenerService)
: base(keyboardInputListenerService) =>
controls = new ObservableCollection<Control>();
/* protected */ internal override void OnKeyPressed(object sender, KeyboardEventArgs args)
{
foreach (Control control in controls)
control.OnKeyPressed(sender, args);
base.OnKeyPressed(sender, args);
}
}
Problem is, I cannot decide which modifier to use for methods such as OnKeyPressed. I wanted to make them protected, but it causes a compiler error:
Error CS1540 Cannot access protected member 'Control.OnKeyPressed(object, KeyboardEventArgs)' via a qualifier of type 'Control'; the qualifier must be of type 'ContainerControl' (or derived from it)
I can make them public, but I do not really think it is a good idea, because there is no reason for it except for resolving the problem caused by a cross-hierarchy call. I made them internal, but there is also a drawback: if anyone will want to create a user control, they will not be able to receive events, so the control will be useless.
The question is how to get access from a derived class to virtual methods of the base class without making the methods public-accessed.
Use protected internal
protected internal virtual void OnKeyPressed(object sender, KeyboardEventArgs args)
{ ... }
The documentation says:
protected internal The type or member can be accessed by any code in the assembly in which it is declared, or from within a derived class in another assembly.

Best way for several classes to share the same attributes in C#

I've already seen some ways to do this attribute sharing, from the most basic (passing attributes per parameter) and interface (which so far was the cleanest way I've found), but would like to know if there are other ways, maybe even better, of doing this, since I am refactoring my main class and would like to avoid having to do this again for a long time.
The problem is the following, I have a mother class that has several children, however according to the need of the company other children were being created and some methods of the children were passed to the mother and today the mother already has 15 attributes and more 60 methods that can be perfectly divided into classes.
My classes are these confused monsters that I'm not proud of, so you should understand why she's crying over refactoring:
public class A
{
protected Form myForm = new Form();
protected WebBrowser myBrowser = new WebBrowser();
protected List<ComplexType1> List1 = new List<ComplexType1>();
protected List<ComplexType2> List2 = new List<ComplexType2>();
protected List<ComplexType3> List3 = new List<ComplexType3>();
protected List<ComplexType4> List4 = new List<ComplexType4>();
protected ComplexType5 myData;
// And more attribute ...
public A() { }
protected virtual void Method1() {}
protected virtual void Method2() {}
protected virtual void Method3() {}
protected virtual void Method4() {}
protected virtual void Method5() {}
// And more and more methods ...
}
public class B : A
{
protected ComplexType6 anotherData;
public B() : base() {}
protected override void Method3() {}
protected override void Method4() {}
protected virtual void Method6() {}
}
public class C : A
{
public C() : base() {}
protected override void Method1() {}
protected virtual void Method6() {}
protected virtual void Method7() {}
}
// And more and more child classes ...
From the looks of it, you have a humungous class which is being inherited by many other class.
The best way to tackle a huge class and coupled with inheritance is to avoid it.
You will have a lot of problems with both the cases, if you have too much functionality it base class you are bound to modify it. Modifying the base class will impact all the derived classes and you it will be difficult to keep track and test it. Coupled with shared variables, you will not know if the base class updated it or the derived class updated it.
I would suggest break down the base class into smaller classes for closely related functionality. Prefer composition over inheritance. This will reduce your member/variable sharing and have a manageable code.

Automatically firing base class functions

I want to ask this question because of some safety mechanism for my code.
This may seem like useless, but it already made me lose much time debugging.
public class AnimalClass
{
virtual void Mod{}
virtual void UpdateSomeValues{}
}
public class CatClass : AnimalClass
{
override void Mod{}
override void UpdateSomeValues{}
}
Is there a way in C# to automatically fire up Cat's UpdateSomeValues function whenever Cat's Mod function is called (without having to call it manually from Cat's Mod function)?
And if possible, make it the same for all derived classes?
No. You could solve that issue by introducing another, protected method that derived classes can override, and make the public one call into it once all the necessary processing is done:
public class AnimalClass
{
public void Mod()
{
// do stuff
ModImpl();
}
protected virtual ModImpl() {}
}
With that derived classes would implement ModImpl() if they want to do some extra processing, and you're sure that // do stuff still happens when Mod is called.

How to instantiate an extended class with a different base implementation?

I'm working with a binary that contains an object and the base class it extends. I want to instantiate the object, but for it to use my own implementation of the base class. I can see in the base class to know what methods I need t extend.
The problem is that the base class implements a method called "WriteFeed" that expects network connections and writes data out to a network stream. I would like it to use my implementation so WriteFeed can instead dump data to console.
I cannot change the existing binaries, only the way I consume and instantiate it.
My only suggestion is to use a composite approach. I'm not sure if this will meet your need or you have visibility access, but it may work.
public class SomeBaseClassInSomeBinary
{
protected virtual void Method1(...) {}
protected virtual void WriteFeed (...) {}
}
public class SomeClassInSomeBinary: SomeBaseClassInSomeBinary
{
protected override void Method1(...) { base.Method1(...); }
protected override void WriteFeed (...) { base.WriteFeed (...); }
}
// **** your code
public class MyCode: SomeBaseClassInSomeBinary
{
private SomeClassInSomeBinary Composite = new SomeClassInSomeBinary();
protected override void Method1(...) { Composite.Method1(...); }
protected override void WriteFeed (...) { your implementation }
}
}
All you need to do is now use your object instead.
Hope this helps.

Categories

Resources