Prevent/Generate warning if subclass calls an overriden member - c#

Given the following pseudo C# code:
public abstract class Worker
{
public void DoWork()
{
Prepare();
Work();
Cleanup();
}
protected abstract void Work();
}
With this design, it is possible, that a derived class (which overrides the Work() method) calls the Work() method directly.
I'm looking for design tips on how to prevent any subclass to do this call, or at least generate a compiler warning.
Why I want to do this?
The Worker actually dispatches the Work() to another thread. DoWork() takes care about the locking.
I know, this is weird. The Work()-body might just consist of a method call to DoMyWork() and the object might call DoMyWork() somewhere else. It's impossible to intercept that.
Anyways. I appreciate any thoughts on that issue.

Thanks to Eris and Corey I think I figured it out. What about this way:
public abstract class Worker
{
public void DoWork()
{
if (Work != null)
{
Prepare();
Work();
Cleanup();
}
}
protected Action Work { private get; set; }
}
public class ImplWorker {
public ImplWorker() {
Work = //whatever
}
}
Still if he really wanted to he can store it somewhere else and stuff. But it goes as far as I can imagine.

If the Work is done using a resource (e.g. remote server, database connection), or it can be changed to be like that, then you could do it like this:
public interface IResource
{
}
public abstract class Worker
{
private class TheResource : IResource
{
// implement
}
public void DoWork()
{
Prepare();
var resObj = new TheResource();
Work(resObj);
// if needed, cleanup/dispose resObj here
Cleanup();
}
protected abstract void Work(IResource resourceObj);
}

This is somewhat of a hack, but you could change the method to be virtual, add a body which calls the new method, and then add an ObsoleteAttribute to it.
protected void DoWork()
{
// New method
}
[Obsolete("This method is deprecated.")]
protected virtual void Work()
{
DoWork();
}
Marking the method as virtual will prevent any existing child classes from breaking, since they were previously required to override Work().

Related

Explanation on how this works?

I have a pretty basic understanding of inheritance and so when using it there are a few moments like this where I find it difficult to understand what's fully happening and it probably doesn't help that I'm most likely not using it properly.
Anyways though I have these 3 classes
public abstract class EffectBase
{
public enum EffectType
{
harm,
help,
self
}
public EffectType type;
public float duration;
public void Activate()
{
Debug.Log("Activating effect");
ApplyEffect();
}
public abstract void ApplyEffect();
public abstract void End();
}
public class Player : MonoBehaviour
{
public List<EffectBase> effects = new List<EffectBase>();
void Update()
{
if (Input.GetKeyDown("q"))
{
Debug.Log("Q pressed");
AddEffect(new SpeedEffect());
}
}
public void AddEffect(EffectBase effect)
{
Debug.Log("Adding effect");
effects.Add(effect);
effect.Activate();
}
}
public class SpeedEffect : EffectBase
{
public override void ApplyEffect()
{
Debug.Log("Speed effect applied");
}
public override void End()
{
Debug.Log("Speed effect ended");
}
}
When I call the AddEffect method I pass a new instance of SpeedEffect (I think it's an instance) as the parameter and then in the AddEffect method I call the Activate method from it, however, in the SpeedEffect class, it doesn't have or override that method so I'm assuming it goes to the base class which does have it and continues and now here's where I get confused in the Activate method it calls the ApplyEffect method, but how does it know to call the one in the SpeedEffect class?
Despite not having an override for Activate() that method still exists in the SpeedEffect class, you just didn't need to write any code for it since its the same code so theres no need to duplicate it.
The code for Activate() calls the ApplyEffect() method for whatever class its being called from. In this case: EffectBase.Activate() and SpeedEffect.Activate() have the same code in terms of reading it, but they are not the same; EffectBase.ApplyEffect() and SpeedEffect.ApplyEffect() are two different methods and each are called from their respective classes.

If I extend a c# interface, can I eat a call?

In this question I mention Unity3D, but applies generally in c#.
Unity3D has an Interface that looks like this ..
public class SomeRobot:MonoBehaviour, IPointerDownHandler
{
public void OnPointerDown(PointerEventData data)
{
Debug.Log("Gets called whenever someone touches the screen...");
}
No problem so far.
I make my own interface..
public interface IFUHandler:IPointerDownHandler
{
void OnBlah (PointerEventData data);
}
Assume I have a daemon or whatever that calls OnBlah for consumers of the interface.
public class SomeRobot:MonoBehaviour, IFUHandler
{
public void OnBlah(PointerEventData data)
{
Debug.Log("Gets called when blah happens...");
}
No problem so far. BUT
public class SomeRobot:MonoBehaviour, IFUHandler
{
public void OnBlah(PointerEventData data)
{
Debug.Log("Gets called when blah happens...");
}
public void OnPointerDown(PointerEventData data)
{
Debug.Log("this DOES still get called also...");
}
In fact, OnPointerDown still gets called. Which makes sense.
BUT .... is there a way for my Interface to eat the calls to OnPointerDown?
So that a consumer subscribing to IFUHandler in fact does NOT get the calls to OnPointerDown?
(But of course gets my OnBlah calls.)
Or am I just suffering "TMIOOK" thinking? (Tied Myself In OO Knots thinking :) )
Simple answer: No.
Possible solutions:
Don't inherit IPointerDownHandler when you don't need it. Why do you need this interface if you aren't going to use it?
Create a Sealed Abstract class with a non-virtual method
public class BaseFUHandler : MonoBehaviour, IFUHandler
{
public abstract void OnBlah(PointerEventData data);
public void OnPointerDown(PointerEventData data)
{
//Gets called, but nothing hapends.
}

How to get list of currently instantiated instances of some dependency in Castle Windsor?

Suppose I have a component Bar that does Foo and notifies about that calling FooHappened method on all services implementing IFooConsumer interface.
I can write Bar like this
class Bar
{
public Bar(IEnumerable<IFooConsumer> fooConsumers) { ... }
public void Foo()
{
// foo-ing
foreach (var f in _fooConsumers) f.FooHappened();
}
}
It will work, but instantiating Bar will instantiate all possible IFooConsumers. What if I need to notify only those IFooConsumers that exist at the moment when Foo happened?
Is there a way to get some kind of tracker that knows about all instantiated instances of IFooConsumer?
I could probably write one myself via subscribing to IWindsorContainer.Kernel.ComponentCreated, but I'm interested if something like that exists? Or maybe there's another way to solve my issue?
You can create a simple facility like the one showing below, that will do the event registration every time a components get's instantiated. The code below here is for using Winsor with Caliburn.Micro. This will also make sure that events get deregistered, which will otherwise result in weird behaviour. In your case I would not have Bar directly fire the event's to all the classes, but rather use a singleton component (like IEventAggregator below) to fire events to multiple classes. This will also make sure that events get deregistered, which will otherwise result in weird behaviour. In the code every class that derives from IHandle will receive events. You can change this according to your needs.
If you have any questions just let me know.
class EventRegistrationFacility : AbstractFacility
{
private IEventAggregator _eventAggregator;
protected override void Init()
{
Kernel.ComponentCreated += ComponentCreated;
Kernel.ComponentDestroyed += ComponentDestroyed;
}
void ComponentCreated(Castle.Core.ComponentModel model, object instance)
{
if (!(instance is IHandle)) return;
if (_eventAggregator == null) _eventAggregator = Kernel.Resolve<IEventAggregator>();
_eventAggregator.Subscribe(instance);
}
void ComponentDestroyed(Castle.Core.ComponentModel model, object instance)
{
if (!(instance is IHandle)) return;
if (_eventAggregator == null) return;
_eventAggregator.Unsubscribe(instance);
}
}
===EDIT====
Combining this with the bouncer as described by Sammy:
public interface IBouncer {
IEnumerable<IFooConsumer> WhoIsInside {get;}
void WelcomeTo(IFooConsumer consumer);
void EscortOut(IFooConsumer consumer);
}
public class Bouncer {
private IList<IFooConsumer> _inside {get;}
void WelcomeTo(IFooConsumer consumer) {
_inside.Add(consumer);
}
void EscortOut(IFooConsumer consumer);
_inside.Remove(consumer);
}
IEnumerable<IFooConsumer> WhoIsInside {
get {
return _inside;
}
}
public Consumer: IFooConsumer {
FooHappened() {
// Do something.
}
// no need to implement constructor/dispose
}
class Bar
{
public Bar(IBouncer bouncer) { ... }
public void Foo()
{
// foo-ing ==> alernatively create a function on Bouncer that does this. And keep WhoIsInside private.
foreach (var f in bouncer.WhoIsInside) f.FooHappened();
}
}
class BouncerRegistrationFacility : AbstractFacility
{
private IBouncer _bouncer
protected override void Init()
{
Kernel.ComponentCreated += ComponentCreated;
Kernel.ComponentDestroyed += ComponentDestroyed;
}
void ComponentCreated(Castle.Core.ComponentModel model, object instance)
{
if (!(instance is IFooConsumer)) return;
if (_bouncer == null) _bouncer = Kernel.Resolve<IEventAggregator>();
_bouncer.WelcomeTo(instance);
}
void ComponentDestroyed(Castle.Core.ComponentModel model, object instance)
{
if (!(instance is IFooConsumer)) return;
if (_bouncer == null) return;
_bouncer.EscortOut(instance);
}
}
Allthough you need some more code for writing the facility, there is no need for FooConsumers to register/unregister themselves. As the registration code must originally be written in all FooConsumers it tends to repeat. In this way the subscription/unsubscription is done as a commission/decommission requirement and only needs to be dealt with once.
P.S. Code is written in notepad and might contain compile errors.
I think that putting the crux of knowing which objects are instantiated on Castle Windsor is not the best way forward; you will certainly need to access some container methods and doing so will link your components to Castle, which shouldn't happen.
What I'd recommend instead is to create a component IBouncer. That component would be injected as singleton in all IFooConsumer which would call it upon being created and disposed (dispose being one option, you could use other methods)
public interface IBouncer {
IEnumerable<IFooConsumer> WhoIsInside {get;}
void WelcomeTo(IFooConsumer consumer);
void EscortOut(IFooConsumer consumer);
}
public Consumer: IFooConsumer {
public Consumer(IBouncer bouncer) {
bouncer.WelcomeTo(this);
}
public Dispose() {
bouncer.EscortOut(this); // dispose pattern ommitted
}
}
Now instead of passing the list of IFooConsumer to your Bar, just add the IBouncer to it and ask which consumers are inside.
class Bar
{
public Bar(IBouncer bouncer) { ... }
public void Foo()
{
// foo-ing
foreach (var f in bouncer.WhoIsInside) f.FooHappened();
}
}

How to make sure nothing gets called until the constructor has finished executing

Consider the following code:
using System.Threading;
public class BaseClass {
private Timer tmrWork;
public BaseClass() {
// read values from config
tmrWork = new Timer(tmrWork_Tick, null, 1, SomeInterval);
}
private void tmrWork_Tick(object state)
{
DoWork();
}
protected abstract void DoWork();
}
public class ChildClass: BaseClass {
public ChildClass() {
// do a bunch of stuff here
// potentially time consuming
}
protected override void DoWork() {
// do stuff
}
}
The intent here is this: based on config values, classes that inherit from the BaseClass will have a method called DoWork called at a certain point.
Because that method gets called on a separate thread (due to usage of the System.Threading.Timer) sometimes DoWork gets called before the ChildClass constructor has finished executing.
How can I make sure that the child constructor has completed until the DoWork gets called?
P.S. The code is in a Windows service.
The safest method is to not initialize the timer when the object is constructed, but instead to provide either an Enabled property or a Start() method to explicitly start the timer after the object is fully initialized. This property/method is set/called by the code that creates the new object, and not from within the constructor itself.
The simplest I could think of
public class BaseClass {
private Timer tmrWork;
protected bool IsReady;
public BaseClass() {
// read values from config
tmrWork = new Timer(tmrWork_Tick, null, 1, SomeInterval);
}
private void tmrWork_Tick(object state)
{
if (IsReady)
DoWork();
}
protected abstract void DoWork();
}
public class ChildClass: BaseClass {
public ChildClass() {
// do a bunch of stuff here
// potentially time consuming
IsReady = true;
}
protected override void DoWork() {
// do stuff
}
}
Or better make IsReady abstract method so that children have to implement it. In solution above (and Daniel's answer) there's always possibility that child class forgets to set the flag (call Initialize)
But really I think there may be something wrong with your design. I don't think Timer should be contained by BaseClass. This way you can have
new ChildClass();
and now suddenly some threads do some work in background.
To me it looks like Timer is some kind of infrastructure code that runs jobs which are implemented in different classes as as such should be extracted from BaseClass. Current solution is also not testable.
But of course I may be wrong because I don't know what real code is doing.
The order of execution of constructors is opposite to that of initialisers, so I would do your setup work in an initialiser.
public class BaseClass {
private Timer tmrWork;
public BaseClass() {
// read values from config
tmrWork = new Timer(tmrWork_Tick, null, 1, SomeInterval);
lock (syncObject)
Init();
}
protected abstract void Init();
private void tmrWork_Tick(object state)
{
lock (syncObject)
DoWork();
}
protected abstract void DoWork();
}
public class ChildClass: BaseClass {
private object syncObject = new object();
protected override void Init() {
lock (syncObject) {
// do a bunch of stuff here
// potentially time consuming
}
}
protected override void DoWork() {
// do stuff
}
}

Propagating a "volatile" property

I put "volatile" because it's only vaguely so.
I have a class which has a property called StopRequested. This flag can be set by other threads at any time, and needs to indicate to my code that it should stop what it's doing and exit (this is a Windows Service based process, and when Stop is called, all processing needs to clean up and stop).
I wish to create some other classes to do the actual brunt of the processing work, however these classes also have to be aware of the "stop" flag. You can't just pass the flag because it will pass a copy, and you can't pass properties as ref types.
So how do you propagate a property that might change at any time into other classes?
The only thing I can think of is to pass a reference to the parent class, but I dislike coupling the worker classes to the parent for one flag. Any suggestions would be appreciated.
EDIT:
Here's a basic example:
public class A
{
public bool StopRequested { get; set; }
private Worker = new Worker();
public void DoWork();
{
worker.DoWork();
}
}
public class Worker
{
public void DoWork()
{
while(!StopRequested)
{
....
}
}
}
You could have each of your worker classes have their own StopRequest property and then just set that whenever StopRequest is flagged.
private List<IStopable> WorkerClasses = new List< IStopable > ()
public Bool StopRequest{
get
{
return _stopRequest;
}
set
{
_stopReqest = value;
foreach (var child in WorkerClasses)
child.StopRequest = value;
}
}
Like Rubens said, use an event. What you described basically defines event to a T:
Propagate a property change to other classes.
There is actually a facility in .NET that provides this already, albeit in a generic way: INotifyPropertyChanged. This interface provides a single event, PropertyChanged, that allows a class to notify any listeners of any property change.
In your case, you could easily provide your own interface that is more specific:
interface IStopNotifier
{
event EventHandler StopRequested;
}
This interface would be implemented by your main work manager (whatever it is), and could propagate itself like so:
class WorkManager: IStopNotifier
{
public event EventHandler StopRequested;
protected void OnStopRequested()
{
if (StopRequested != null) StopRequested(this, new EventArgs());
}
public void StopAllWorkers()
{
OnStopRequested();
}
public Worker CreateWorker<T>()
where T: Worker
{
var worker = new T(this);
return worker;
}
}
class abstract Worker: IDisposable
{
public Worker(IStopNotifier stopNotifier)
{
stopNotofier.StopRequested += HandleStopRequested;
}
private IStopNotifier m_stopNotifier;
private bool m_stopRequested = false;
internal void HandleStopRequested(object sender, EventArgs e)
{
m_stopRequested = true;
}
public void Dispose()
{
m_stopNotifier.StopRequested -= HandleStopRequested;
}
}
Why don't to create an event to handle stop requests?

Categories