Reputation: 131
I'm looking for tips on the best way of implementing the following:
I have a class which recieves input, say, every second and fires an event upon recieving this input (sending with it information on the input).
This event is subscribed to by several other classes.
Each of these classes has a:
int
field), Condition
(which
checks for a condition based on the input from the event) and a
method called run.When the event is fired, all the classes invoke the Condition
method. provided the method returns true, I would like the run method to be invoked on the class with the highest ranking only.
The way I am implementing it is when the event is fired, all the classes add the ranking and the run method to a list (0 ranking is added if the condition is not met).
When the list reaches a set amount, it picks out the the highest ranking and invokes the associated method.
Here is the code:
class mainClass
{
void Input(int input)
{
goEvent?.Invoke(input);
}
public event Action<int> goEvent;
public int TEMP_COUNTER=0;
public int TEMP_RANK=0;
public string TEMP_METHODNAME = "";
}
class class1
{
//...
int rank = 4;
bool condition(int n)
{
if(n > 10)
return true;
else
return false;
}
void run(){}
void mainClassEventHandler(int input)
{
if (condition(input)
{
addtolist(rank,run)
}
else
{
addtolist(0,null)
}
}
}
class class2
{
//...
int rank = 3;
bool condition(int n)
{
if(n > 20)
return true;
else
return false;
}
void run(){}
void mainClassEventHandler(int input)
{
if (condition(input)
addtolist(rank,run)
else
addtolist(0,null)
}
}
Upvotes: 0
Views: 38
Reputation: 445
I don't think the subscription model is appropriate for this problem. Your "MainClass" needs to function more as an orchestrator (electing the hightest ranking runnable) to execute vs blindly producing an event.
So, lets start with the interface for your "runner" classes:
interface RankedRunner
{
// The rank of the runner (this must be immutable).
int Rank { get; }
// Whether we can run this runner.
bool Runnable(int input);
// Run the runner.
void Run();
}
Now lets add some implementations:
class Runner1 : RankedRunner
{
public int Rank => 3;
public void Run()
{
}
public bool Runnable(int input)
{
return input > 20;
}
}
class Runner2 : RankedRunner
{
public int Rank => 4;
public void Run()
{
}
public bool Runnable(int input)
{
return input > 10;
}
}
Finally, let's orchestrate calling the runners based on some input:
class Orchestration
{
private SortedList<RankedRunner, RankedRunner> runners;
Orchestration()
{
// We need to sort our runners based on their rank. If two runners
// have the same rank then use the object comparator.
// Note that x and y get swapped so the largest rank will be ordered first.
this.runners = new SortedList<RankedRunner, RankedRunner>(
Comparer<RankedRunner>.Create(
(x, y) =>
{
return x.Rank == y.Rank
? Comparer<RankedRunner>.Default.Compare(y, x)
: Comparer<int>.Default.Compare(y.Rank, x.Rank);
}));
}
Orchestration addRankedRunner(RankedRunner runner)
{
this.runners.Add(runner, runner);
return this;
}
void Input(int input)
{
// Find the highest ranked runner that is runnable.
foreach(RankedRunner runner in runners.Values)
{
if(runner.Runnable(input))
{
runner.Run();
break;
}
}
}
}
Example Usage:
var orchestration = new Orchestration();
orchestration.addRankedRunner(new Runner1());
orchestration.addRankedRunner(new Runner2());
orchestration.Input(5);
orchestration.Input(10);
orchestration.Input(50);
Upvotes: 2