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:
"ranking" (an int field),
a bool method 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)
}
}
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);
Related
I'm new to passing delegates and was wondering if the following code is possible to do?
CommandQueue.AddCommand(
new CommandItem(
group.MyGroupActionMovement(
new Vector3(-1000,-1000,-1000))));
ok to elaborate I'm going to do a code dump of my bad attempt at the command pattern...
So I'm trying to create a queue of commands. Starting with just the movement command. It takes a vector3 as a parameter. Other Commands will have different parameters like enums and game objects.
This is supposed to be my interface for commands/actions but, I've been messing with it to see what I can do.
public class IGroupAction: MonoBehaviour
{
public delegate bool Del(Vector3 destination);
public virtual bool Execute()
{
return true;
}
}
This is supposed to be the command/action unit/item
public class GroupActionItem
{
public IGroupAction MyGroupAction;
public GroupActionItem(IGroupAction.Del action)
{
}
public bool PerformAction()
{
return MyGroupAction.Execute();
}
}
This is the command pattern that I've completed so far
public class GroupAction
{
public List<GroupActionItem> Actions;
public GroupAction()
{
Actions = new List<GroupActionItem>();
}
public void AddAction(GroupActionItem groupActionItem)
{
Actions.Add(groupActionItem);
}
public void ClearActions()
{
Actions.Clear();
}
public void PerformActions()
{
if (Actions.Count >= 1)
{
if(Actions[0].PerformAction())
{
Actions.Remove(Actions[0]);
}
}
}
}
This is where I execute the movement command
public class GroupActionMovement : IGroupAction
{
public override bool Execute()
{
return Movement();
}
public bool Movement(Vector3 destination)
{
return true;
}
}
public class Group : MonoBehaviour
{
public GroupActionMovement MyGroupActionMovement;
}
This is the execution of the coded behavior.
public class Player : MonoBehaviour
{
public Dictionary<Group,GroupAction> PlayerGroupsActions;
public List<Group> Groups;
void Start()
{
PlayerGroupsActions = new Dictionary<Group, GroupAction>();
Groups = GetComponentsInChildren<Group>().ToList();
foreach (Group group in Groups)
{
GroupAction playerGroupActions = new GroupAction();
PlayerGroupsActions.Add(group,playerGroupActions);
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha1))
{
//remove the foreach
foreach (Group group in Groups)
{
//directly apply the group
PlayerGroupsActions.TryGetValue(group, out GroupAction playerGroupActions);
if (playerGroupActions != null)
{
playerGroupActions.AddAction(new GroupActionItem(group.MyGroupActionMovement.Movement));
}
}
}
foreach (Group group in Groups)
{
PlayerGroupsActions.TryGetValue(group, out GroupAction playerFormationActions);
if (playerFormationActions != null)
{
if (playerFormationActions.Actions.Count != 0)
{
playerFormationActions.PerformActions();
}
}
}
}
}
I'm sorry if this isn't the best explanation of what is going on or, that a code dump is not the best way to explain what i'm doing.
don't pass it as a method, use something like this
CommandQueue.Command += doSomething;
void doSomething()
{
//doSomething
}
So that whenever the function CommandQueue.Command is run in the seperate class it will also run the doSomething() void in the main class
A delegate is not a method call, but the method it self, for the receiver to call it, whenever its needs to, with the parameters it wants.
Here is an example:
public delegate int MyDelegate(Vector3 vec);
public class MyCallingClass
{
public void DoSomething(MyDelegate method)
{
// Do something.
int result = method(new Vector3(-1000, -1000, -1000));
// Do something else.
}
}
public class MyClass
{
public static int MyStaticMethod(Vector3 arg)
{
// Do something with arg.
return x;
}
int MyMethod(Vector3 arg)
{
// Do something with arg.
return x;
}
private void DelegateWork()
{
MyCallingClass c = // Get an instance of MyCallingClass.
c.DoSomething(this.MyMethod);
c.DoSomething(MyClass.MyStaticMethod);
}
}
Multiple things to understand here:
At line c.DoSomething(this.MyMethod), the this is captured into the delegate you pass, meaning that when MyCallingClass.DoSomething will call the delegate, it will be called on the instance of MyClass. The line c.DoSomething(MyClass.MyStaticMethod) will call it with no instance, because it is a static method.
This is the method MyCallingClass.DoSomething that decides what parameters to pass, not the one that provides the delegate.
If you need the caller to provide arguments and the calling part to just decide when to call but not deciding what arguments to pass, then you can capture the argument ahead of time, and pass a delegate without argument, as follow.
public delegate int MyDelegate(); // No arguments anymore.
public class MyCallingClass
{
public void DoSomething(MyDelegate method)
{
// Do something.
int result = method(); // Not passing arguments anymore.
// Do something else.
}
}
public class MyClass
{
// ...
private void DelegateWork()
{
MyCallingClass c = // Get an instance of MyCallingClass.
c.DoSomething(() => this.MyMethod(new Vector3(-1000, -1000, -1000)));
c.DoSomething(() => MyClass.MyStaticMethod(new Vector3(-1000, -1000, -1000));
}
}
If you are not familiar with the syntax () => ..., this is a lambda expression, you can see it as an anonymous function created on-the-fly. It still respects the prototype returning an int and taking no parameters. The lambda expression now captures the construction of the Vector3 instance, and so this value will be used when the lambda will be called. A very important aspect to understand is that the values in the lambda expressions are evaluated when the lambda is called, not when it is created (lazy evaluation).
You do not have to use a specific delegate but instead you can use a Func<Vector3, int>, as follow:
// Not actually needed.
// public delegate int MyDelegate(Vector3 vec);
public class MyCallingClass
{
public void DoSomething(Func<Vector3, int> method)
{
...
}
}
I am trying to build a unit test.
The class Position is implemented in a third party library. But for my unit test I need the Size property to be set to a specific value.
public class Position
{
private double _size;
private double Size
{
get
{
return _size;
}
internal set
{
_size = value;
}
}
}
I read this post: How do you create a unit-testing stub for an interface containing a read-only member?
but could not figure out how to make it work for me.
This is the class under test (just a simplified example). The posargument in the CalcPositionMetric() method must be of type Position:
public class PositionMetrics
{
public PositionMetrics()
{}
public double CalcPositionMetric(Position pos)
{
return 2 * pos.Size;
}
}
Here is a piece of my unit test:
using NUnit.Framework;
using NMock;
[TestFixture]
public class PositionUnitTests
{
[Test]
public void TestPosition()
{
Mock<Position> tmpPosMock = mFactory.CreateMock<Position>();
tmpPosMock.Expects.One.GetProperty(v => v.Size).WillReturn(7); /* !!! Exception !!! System.ArgumentException : mock object position has a getter for property Size, but it is not virtual or abstract */
/* Execute Test with tmpPositions*/
PositionMetrics pm = new PositionMetrics();
double result = pm.CalcPositionMetric(tmpPosMock.MockObject)
Assert.AreEqual(14, result);
}
}
But as you can see I get an exception. Could somebody help me to resolve this problem? Any other solutions are also welcome!
Cheers
Konstantin
New answer for the updated question I suggest you to introduce some kind of a proxy interface for that. See the code below:
interface IPosition {
int Size { get; }
}
class Position { //in 3rd party lib
public int Size {
get { return 5; }
}
}
class RealPosition : IPosition { //use this as your real object instead of using Position directly
private Position position;
public RealPosition(Position position) {
this.position = position;
}
public int Size {
get { return position.Size; }
}
}
class MockPosition : IPosition { //use this for testing
public int Size{ get; set; }
}
public class Program {
static void Main(string[] args) {
var pos = new MockPosition { Size = 7 };
Console.WriteLine(Calc(pos)); //prints 14
Console.ReadLine();
}
static int Calc(IPosition pos) { //change your method signature to work with interface
return pos.Size * 2;
}
}
Old answer If the class is not sealed you don't need any mocking libraries. Just use the new modifier for the required properties like this:
class Position {
public int Size { get { return 5; } }
}
class MockPosition : Position {
public new int Size { get; set; }
}
....
var mock= new MockPosition();
mock.Size = 7;
To use these items in some sort of list you'll have to cast them like this:
var items = new List<Position>();
for (int i = 0; i < 5; i++) {
items.Add(new MockPosition { Size = i });
}
foreach (var item in items.Cast<MockPosition>()) {
Console.Write("{0}\t", item.Size); //prints 0 1 2 3 4
}
If it is sealed and the property is not virtual than you'll have to use some other techniques, Moq (which I guess you are using) does not allow that
I'm making a game using Monogame, and I've been trying to figure out how to implement a function that acts similarly to AS3's and GML's with statement.
So far I have a system that works, but not entirely the way I want it to. I store my GameObjects in a Dictionary of Lists. This is so I can get to the specific type of object I want to access without having to loop through a list of ALL objects. The key used is the name of the type.
public static Dictionary<string, List<GameObject>> All =
new Dictionary<string, List<GameObject>>();
I access all of a specific type of object using AllOf. If a List containing that type exists in the Dictionary, it returns that List, else it returns an empty list.
public static List<GameObject> AllOf(Type type)
{
string key = type.Name;
if(All.ContainsKey(key))
{
return All[key];
}
return new List<GameObject>();
}
An example of how these are implemented
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
}
}
But I'd rather use something similar to the AS3/GML with statement, which would also allow for other, non-member codes to be executed.
with(typeof(Dummy))
{
Update(gameTime);
foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
Is there a way to accomplish this? My end goal is just to make my code look a little cleaner, and make it easier to make a lot of changes without having to type out a for loop each time.
No such syntax exists in C#, but you can access methods within the for that have nothing to do with the collection:
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
}
Note that you can also use foreach, which is a little cleaner if you don't need the indexer:
foreach(var item in list)
{
item.Update(gameTime);
item.foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
try
using(Object myObject = new Object()){
}
i think this might be what your looking to use?
I have a small solution for this use case. This may be a bit of a necropost, but it is a pretty neat solution. Additionally, I think all of the C# features that are required existed back when this question was asked.
You can do something very similar to the GML with(x){} by using some form of delegate as a parameter to a static method, and passing a lambda as that parameter. The function can even be genericised, and you can call it without the class name by the using static statement. You will need to explicitly provide the typed/named parameter, but it is possible. You would need to hook it up to your own types, but the general idea is:
namespace NiftyStuff {
public static class With {
public static void with<T>(Action<T> proc) where T : GameObj {
var typeName = typeof(T).Name;
foreach (var item in GameObj.AllOf(typeName)) { proc((T)item); }
}
}
public class GameObj {
private static Dictionary<string, List<GameObj>> All = new Dictionary<string, List<GameObj>>();
public static List<GameObj> AllOf(string name) {
return All.ContainsKey(name) ? All[name] : null;
}
public static void Add(GameObj foo) {
string typeName = foo.GetType().Name;
List<GameObj> foos = All.ContainsKey(typeName) ? All[typeName] : (All[typeName] = new List<GameObj>());
foos.Add(foo);
}
public float x, y, angle;
public GameObj() { x = y = angle = 0; }
public void Destroy() { AllOf(GetType().Name)?.Remove(this); }
}
public class Enemy : GameObj {
public float maxHealth, curHealth;
public Enemy() : base() { maxHealth = curHealth = 300; }
public Enemy(float health) : base() { maxHealth = curHealth = health; }
public bool Damage(float amt) {
if (curHealth > 0) {
curHealth -= amt;
return curHealth <= 0;
}
return false;
}
}
public class Pumpkin : GameObj {
public bool exists = false;
public Pumpkin() : base() { exists = true; }
public bool LookAt() { return (exists = !exists); }
}
}
Actually using the above code would work as follows:
using NiftyStuff;
using static NiftyStuff.With;
//...
with ((Enemy e) => {
if (e.Damage(50)) {
Log("Made a kill!"); // Whatever log function you have...
}
});
with ((Pumpkin p) => {
if (p.LookAt()) {
Log("You see the pumpkin");
} else {
Log("You no longer see the pumpkin");
}
});
While not exactly like GML's with statement, it would at least let you run code against all of the registered objects of some type.
One important note is that you can't destroy objects inside of a with this way (due to concurrent modification of a collection while iterating it). You would need to collect all objects to be destroyed, and then remove them from the list in All, typically in a game loop this is done at the end of a frame.
Hope this helps, despite being 2 years out of date.
I'm trying to model blood flow. As simple as it gets I am trying to have an event (TimerTick) trigger the transfer of a resource object from unit A to unit B, B's to C, C's to A. I can't seem to have reproducible transfer of the resources from one iteration to another, and I've tried a lot more of different ways than what's pasted below.
The units are connected as a triangle after construction. I'm aware that this leaves the first unit to be erroneous, and have tried numerous ways to deal with it (and I'm not sure if that is the only problem) but since none have worked I won't post them.
An idea of event set-up where any one unit doesn't need to know about any others would be totally appreciated. But just a way to make this work would also be appreciated.
class Unit{
Resource currentResource;
Resource incomingResource;
Unit preUnit;
Unit postUnit;
public Unit( int resource, Timer t)
{
this.currentResource = new Resource(resource);
t.TimerTick += T_TimerTick;
}
private void T_TimerTick(object sender, TimerTickEventArgs e)
{
postUnit.receiveResource(currentResource);
currentResource = incomingResource;
}
void receiveResource(Resource resource)
{
incomingResource = resource;
}
//pre and post units connected appropriately to Cycle ...-A-B-C-A-...
// with one cycle per TimerTick
}
I would suggest Inversion of control with Observer pattern
Here is a working setup, to explain my suggestion. In my code, each unit just increments the resource by 1.
And gererates the following output
*Initiating Unit A value 1
Unit A, output 1
Unit B, input 1
Unit B, output 2
Unit C, input 2
Unit C, output 3
Unit A, input 3
Unit A, Cycle complete*
client code
IInitiatorUnit A = new InitiatorUnit("A");
IUnit B = new Unit("B");
IUnit C = new Unit("C");
B.RegisterUnit(A); // B is listening to A
C.RegisterUnit(B); // C is listening to B
A.RegisterUnit(C); // A is listinig to C
void heartBeatTimer_Tick(object sender, EventArgs e)
{
A.GenerateResource(1); // Start the process
}
I have designed unit such that it takes an input, processes it & fires an event for
interface IUnit
{
event EventHandler<ResourceGeneratedEventArgs> ResourceGenerated;
void RegisterUnit(IUnit inputUnit);
string Name { get; }
}
class Unit : IUnit
{
IUnit mInputUnit;
public event EventHandler<ResourceGeneratedEventArgs> ResourceGenerated;
public string Name { get; private set; }
public Unit(string name)
{
this.Name = name;
}
public void RegisterUnit(IUnit inputUnit)
{
this.mInputUnit = inputUnit;
this.mInputUnit.ResourceGenerated += mInputUnitResourceGenrated;
}
void mInputUnitResourceGenrated(object sender, ResourceGeneratedEventArgs inputResource)
{
//take the input resorce. pocess it & fire the event;
//I'm just adding 1 to it as sample
int outputResource = inputResource.Resource + 1;
Console.WriteLine("Unit {0}, input {1} ", this.Name, inputResource.Resource, outputResource);
OnResourceGenerated(outputResource);
}
protected virtual void OnResourceGenerated(int outputResource)
{
Console.WriteLine("Unit {0}, output {1}", this.Name, outputResource);
if (ResourceGenerated != null)
ResourceGenerated(this, new ResourceGeneratedEventArgs(outputResource));
}
}
public class ResourceGeneratedEventArgs : EventArgs
{
public ResourceGeneratedEventArgs(int resource)
{
Resource = resource;
}
public int Resource { get; private set; }
}
/// <summary>
/// This is just to start the process here, Nothing great here
/// </summary>
interface IInitiatorUnit : IUnit
{
void GenerateResource(int initialValue);
}
class InitiatorUnit : Unit, IInitiatorUnit
{
//prevents the cycle from going on & on
bool resetFlag;
public InitiatorUnit(string name):base(name)
{
}
public void GenerateResource(int initialValue)
{
resetFlag = false;
Console.WriteLine("Initiating Unit {0} value {1}", this.Name, initialValue);
OnResourceGenerated(initialValue);
}
protected override void OnResourceGenerated(int outputResource)
{
//Dont raise the event. if the cycle has completed
if (resetFlag == false)
{
resetFlag = true;
base.OnResourceGenerated(outputResource);
}
else
{
//do nothing, cycle has completed
Console.WriteLine("Unit {0}, Cycle complete", this.Name);
}
}
}
Edit 1 : Approach for very large number of units
In my 1st approach, each unit called the subsequent one creating a chain, something like this -
As the nodes would increase so would be the depth of call stack, therefore when the number reaches in thousands we can overrun the stack limit causing a stack over flow.
Therefore the new approach is a just uses an iterates over the units, giving each unit a request, getting a response back and feeding the response to the subsequent unit as request. Something like this -
Here is a working sample & it generates the following output -
Unit A, input 0
Unit A, output 1
Unit B, input 1
Unit B, output 2
Unit C, input 2
Unit C, output 3
Cycle completed result 3
Client Code
private void ClientCode()
{
// Create an array of units
IUnit[] units = new IUnit[] {
new Unit("A"), // A will be called 1st . It needs to be given an initial value to start processing
new Unit("B"), // B will get A's Output to process.
new Unit("C"), // C will get B's Output to process.
};
// pass the array to workflow to process
cycle = new WorkFlow(units);
Console.ReadLine();
}
Heart beat timer
void heartBeatTimer_Tick(object sender, EventArgs e)
{
var result = cycle.Execute(new Resource(0)); // starting the cycle with initial value of 0
Console.WriteLine("Cycle completed result {0}", result.Value);
}
The infrastructure is much simpler now,
interface IUnit
{
Resource ProcessResource(Resource inputResource);
string Name { get; }
}
class Unit : IUnit
{
public string Name { get; private set; }
public Unit(string name)
{
this.Name = name;
}
public Resource ProcessResource(Resource inputResource)
{
//take the input resorce. pocess it & fire the event;
//I'm just adding 1 to it as sample
int outputResource = inputResource.Value + 1;
Console.WriteLine("Unit {0}, input {1} ", this.Name, inputResource.Value);
Console.WriteLine("Unit {0}, output {1} ", this.Name, outputResource);
return new Resource(outputResource);
}
}
class WorkFlow
{
IUnit[] mUnits;
public WorkFlow(IUnit[] units)
{
this.mUnits = units;
}
public Resource Execute(Resource initiatingResource)
{
Resource result = initiatingResource; // initialise result with the input of the cycle.
for (int i = 0; i < mUnits.Length; i++)
{
// the result is passed as input.
//IUnit.ProcessResource function gives back a new result which is encached as input for subsequent resource
result = mUnits[i].ProcessResource(result);
}
return result; // after all are processed,
}
}
public class Resource
{
public Resource(int resourceValue)
{
Value = resourceValue;
}
public int Value { get; private set; }
}
Hope all will work fine now. Please write me a comment if any bit is unclear.
Are those elements and method named, Unit, within a class which is also named Unit?
Try moving the methods and elements to another class.
I would make three static classes for your units:
public static class UnitA
{
var foo1;
var foo2;
}
public static class UnitB
{
var foo1;
var foo2;
}
public static class UnitC
{
var foo1;
var foo2;
}
For each tic, you can handle the resources from any other class:
FooHandler_Tick
{
// Store C's content.
var tempFoo1 = UnitC.foo1;
var tempFoo2 = UnitC.foo2;
// B to C.
UnitC.foo1 = UnitB.foo1;
UnitC.foo2 = UnitB.foo2;
// A to B.
UnitB.foo1 = UnitA.foo1;
UnitB.foo2 = UnitA.foo2;
// C to A.
UnitC.foo1 = tempFoo1;
UnitC.foo2 = tempFoo2;
}
Does this work with your project?
I have a function Parent() and a boolean Class Property Watch with default value true.
This fn Parent() is calling several Child functions.
Lets assume during execution of this function or any of the child functions Watch Changes its value to false , i want the execution to stop and exit the Parent function.
Parent is returning void.
This is a single threaded execution , no async and Task constructs being used
I think the easiest thing to do is to use exceptions for this:
public class TestClass
{
public void ParentMethod()
{
try
{
ChildMethod1();
ChildMethod2();
}
catch (InvalidStateException ise)
{
return;
}
}
public void ChildMethod1()
{
//do stuff, and then if the "watch" is set to true:
throw new InvalidStateException();
}
public void ChildMethod2()
{
//do stuff, and then if the "watch" is set to true:
throw new InvalidStateException();
}
}
public class InvalidStateException : Exception { }
Here I've defined a new exception InvalidStateException that the ChildMethodX can raise when it wants the parent method to stop execution. In the parent method you try/catch all the child calls, and when one throws, it stops the execution and skips into the catch.
Note: Exceptions occur because something exceptional happens. If you expect that this would be a normal flow of logic, then I would implore you to try something that avoids exceptions. Exceptions are expensive performance wise. For example, without using exceptions you could do something like:
public class TestClass
{
public bool Watch { get; set; }
public void ParentMethod()
{
Func<bool> c1Call = () => { Child1Method(); return Watch; };
Func<bool> c2Call = () => { ChildMethod2(); return Watch; };
if (c1Call())
return;
if (c2Call())
return;
}
public void Child1Method()
{
//Do something, then this happens:
Watch = true;
}
public void ChildMethod2()
{
//Do something, then maybe this happens:
Watch = true;
}
}
Where you could modify the Func<> delegates to take any number of arguments. There are a dozen ways to skin this cat, but almost all of them involve checking the flag after calling the function to determine if you want to exit or not. If you functions return void, consider changing them to return bool so you could do something like:
if (ChildMethod1()) return;
Which is pretty concise. Otherwise you can use strange combinations of lambda's and delegates, but when you get down to it you have to ask yourself, is avoiding typing a couple extra "if" statements worth the loss in code maintainability?
Here is a demo mock up how you can construct that.
It demonstrates a workflow where Child2 sets the variable to false and exits after that and therefore never executed Child3.
However I would suggest to have the child functions return a bool instead. Seems not a good design what you are suggesting for a single threaded application.
public class Test
{
public bool Watch { get; set; }
public Test()
{
this.Watch = true;
}
public void Parent()
{
this.Child1();
if(this.Watch == false)
{
return;
}
this.Child2();
if(this.Watch == false)
{
return;
}
this.Child3();
if(this.Watch == false)
{
return;
}
}
public void Child1()
{
//Do stuff
}
public void Child2()
{
this.Watch = false;
}
public void Child3()
{
//Do stuff
}
}
You can either execute each Child function in a different thread and have a loop in the Parent function monitor the Watch value or you can check the Watch value after each Child call. Without a code example or more information, it is difficult to answer.
fn Parent()
{
childfn();
if( !Watch )
return;
}
Though might be better to have child functions return bool and check that rather than use class property.
i assume this is yr code structure.. if my assumption is wrong please correct me
I also have a question - all the child functions have same signature ? if so I'll suggest approach based on delegates. Otherwise here is a simple example
bool Watch { get; set; }
// Parent is control center, calling one child after another
void Parent()
{
ChildOne(1);
if (Watch == false)
return;
ChildTwo(1,3);
if (Watch == false)
return;
}
/// signature type 1
void ChildOne(int a)
{
}
/// signature type 2
void ChildTwo(int a, int b)
{
Watch = false;
}
EDIT 1
here is the approach if all functions have same signature
class ChildFuntionExecutor
{
public Func<int,int> ChildFuntion;
public int Operand1;
public void Evaluate()
{
ChildFuntion(Operand1);
}
}
bool Watch { get; set; }
// Parent is control center, calling one child after another
void Parent()
{
// register all child functions
List<ChildFuntionExecutor> childFuntionQueue = new List<ChildFuntionExecutor>();
childFuntionQueue.Add(new ChildFuntionExecutor { Operand1 = 10, ChildFuntion = this.ChildOne });
childFuntionQueue.Add(new ChildFuntionExecutor { Operand1 = 10, ChildFuntion = this.ChildOne });
foreach (var item in childFuntionQueue)
{
item.Evaluate();
if (Watch == false)
return;
}
}
/// signature type 1
int ChildOne(int a)
{
return a * 10;
}
/// signature type 1
int ChildTwo(int a)
{
Watch = false;
return a * 10;
}