Cyclic transfer of Object - c#

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?

Related

C# There is no argument given that corresponds to the required

I am receiving an error: There is no argument given that corresponds to the required formal parameter 'x' of ReadingMaterial.By(string). I'm looking for a little guidance as to why there is an error. Is my syntax wrong, or is there something else I'm missing? I have been trying to learn C# by using some online tutorials and trying to change them up a bit.
namespace ReadingMaterials
{
class Presentation
{
static void Main(string[] args)
{
aForm Form = new aForm(); // available in hardcopy form aForm.availForm
Online O = new Online(); // amtBlogs, amtBooks
Book B = new Book(); // hardCover, softCover
Magazine M = new Magazine(); // numArticles
O.blog(5); //contains 5 blogs
O.oBook(3); //contains 3 online books
O.By("Beck"); //Written by Beck
O.words(678); //with 678 combined words
O.pics(1); // with one pic
Console.WriteLine("The auther {0} ", O.By());
Form.availForm();
B.hardCover(10); //10 hardcover books
B.softCover(2); //2 softcover books
B.By("Bruce"); //Writen by Bruce
B.words(188264); //words combined
B.pics(15); //15 pictures
Form.availForm();
M.articles(5); //5 articles
M.By("Manddi"); //Writen by Manddi
M.words(18064);//combined words
M.pics(81); //81 pictures
Form.availForm();
}
}
class ReadingMaterial
{
protected int amtWords;
string author;
protected int pic;
public void words(int w)
{
amtWords = w;
}
public void By(string x)
{
author = x;
}
public void pics(int pi)
{
pic = pi;
}
}
class Online : ReadingMaterial
{
int amtBlogs;
int amtBooks;
public void blog(int s)
{
amtBlogs = s;
}
public void oBook(int b)
{
amtBooks = b;
}
}
class Book : ReadingMaterial
{
int hard;
int soft;
public void hardCover(int h)
{
hard = h;
}
public void softCover(int s)
{
soft = s;
}
}
class Magazine:ReadingMaterial
{
int numArticles;
public void articles(int a)
{
numArticles = a;
}
}
interface IPrintable
{
void availForm();
}
class aForm : IPrintable
{
public void availForm ()
{
Console.WriteLine("Available in hard copy form!");
}
}
}
Console.WriteLine("The auther {0} ", O.By()); is the culprit. O.By() expects a string, and the By() function sets the author, but doesn't return any string. Since you've set the author using the By() function, you can make the author a public field, and do Console.WriteLine("The auther {0} ", O.author);
The problem is that you are calling By without any parameters in this line:
Console.WriteLine("The auther {0} ", O.By());
You can add a method to get the value instead:
class ReadingMaterial
{
...
public string GetBy()
{
return author;
}
....
}
Anyways, you might want to use properties instead of functions. You can look at the code working in here
class ReadingMaterial
{
public string Author {get;set;}
...
}
static void Main(string[] args)
{
...
O.Author = "Beck"; //Written by Beck
...
Console.WriteLine("The auther {0} ", O.Author);
}
You have defined the By method like this, with a parameter:
public void By(string x)
{
author = x;
}
But you are trying to call it without a parameter:
Console.WriteLine("The auther {0} ", O.By()); // not passing a parameter to 'By()'
If you want to access the author value of ReadingMaterial here then I would suggest making it a public property rather than a private field:
class ReadingMaterial
{
protected int amtWords;
public string Author { get; private set;}
// skipped
public void By(string x)
{
Author = x;
}
All of which kinds of begs the question - why use methods to set the values at all? Why not just use properties, as suggested below by #CarlosGarcia?

Communication implementation between these classes

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);

Can I create a pointer to poll a float from any source?

Is there a way to access all the different types of object inherited from the same class using the same reference in an object without hard-coding it?
I'm developing on unity and I want to add a module in my game that could watch any particular float in a GameObject to then change another float in another GameObject once it reaches a certain value.
As an example: A "Trigger" Object/Module which set the value of Hunger=1 in a brain Object when the value of Fullness<0.5 is reached in a stomach Object.
As I'll have a big number of possible combinations I don't want to hardcode it by creating a daughter of the Trigger Class for each of them.
My initial idea was to use pointers that would be directed to the good floats to watch/change upon initialization. But apparently, we can't use unsafe code inside iterators (IEnumerator) so I'm not sure how to poll the value of Fullness.
To give an example of what I would like :
public Class Trigger{
private float* ToPoll;
private float* ToChange;
public void SetTrigger(float* poll, float* change){
ToPoll = poll;
ToChange = change;
// the loop would be a IEnumerator, not a litteral loop
while(*ToPoll < 0.5f){
sleep(0.1)
}
*ToChange = 1f
}
}
void Main(){
Trigger trigger1, trigger2;
trigger1.SetTrigger(&Stomach.fullness, &Brain.hunger)
trigger2.SetTrigger(&Sun.activityLevel, &Earth.radiationLevel)
// ^ Literally any float from any object
}
Do you have any ideas how to or better ways to implement it?
Expanding on the answer from #kara, the following code implements independent Stomach and Brain objects, and uses Being to wire them up.
What Being knows about Stomach:
it has a NeedsFoodEvent
What Being knows about Brain
there is a OnRaiseIsHungryEvent (i.e. a "hungry" signal -- who cares where it came from)
it has a IsHungryEvent
Keep in mind that in a real implementation there would likely be other objects listening for those events. e.g. maybe you have an emotion system that would switch to "hangry" and a goal-based AI that would switch to food-seeking mode. Neither system would need to be aware of the other, but both could respond to signals from the Brain. In this trivial implementation the Being responds to the Stomach signal and both notifies and responds to the Brain.
The important take-away from this is not the specific method of raising and responding to events (in this case the default .Net mechanism) but the fact that neither object knows anything about the internals of the other (see the different implementations of HumanStomach and ZombieStomach) and instead the connection is wired up at a more appropriate level (Being in this case). Also note the reliance on interfaces, which allows us to do things like create hybrid beings (i.e. pairing a ZombieBrain with a HumanStomach).
Code was written/tested with .Net Core CLI as a console app, but it should be compatible with most any version of .Net > 3.5.
using System;
using System.Linq;
using System.Threading;
namespace so_example
{
public class Program
{
static void Main(string[] args)
{
var person1 = new Being("Human 1", new HumanBrain(), new HumanStomach());
var zombie1 = new Being("Zombie 1", new ZombieBrain(), new ZombieStomach());
var hybrid1 = new Being("Hybrid 1", new ZombieBrain(), new HumanStomach());
var hybrid2 = new Being("Hybrid 2", new HumanBrain(), new ZombieStomach());
Console.WriteLine("Hit any key to exit");
Console.ReadKey();
}
}
public class HungryEventArgs : EventArgs
{
public string Message { get; set; }
}
public interface IStomach
{
event EventHandler<HungryEventArgs> NeedsFoodEvent;
}
public class Stomach : IStomach
{
public event EventHandler<HungryEventArgs> NeedsFoodEvent;
protected virtual void OnRaiseNeedsFoodEvent(HungryEventArgs e)
{
EventHandler<HungryEventArgs> handler = NeedsFoodEvent;
if (handler != null)
{
handler(this, e);
}
}
}
public class HumanStomach : Stomach
{
private Timer _hungerTimer;
public HumanStomach()
{
_hungerTimer = new Timer(o =>
{
// only trigger if breakfast, lunch or dinner (24h notation)
if (new [] { 8, 13, 19 }.Any(t => t == DateTime.Now.Hour))
{
OnRaiseNeedsFoodEvent(new HungryEventArgs { Message = "I'm empty!" });
}
else
{
Console.WriteLine("It's not mealtime");
}
}, null, 1000, 1000);
}
}
public class ZombieStomach : Stomach
{
private Timer _hungerTimer;
public ZombieStomach()
{
_hungerTimer = new Timer(o =>
{
OnRaiseNeedsFoodEvent(new HungryEventArgs { Message = "Need brains in stomach!" });
}, null, 1000, 1000);
}
}
public interface IBrain
{
event EventHandler<HungryEventArgs> IsHungryEvent;
void OnRaiseIsHungryEvent();
}
public class Brain : IBrain
{
public event EventHandler<HungryEventArgs> IsHungryEvent;
protected string _hungryMessage;
public void OnRaiseIsHungryEvent()
{
EventHandler<HungryEventArgs> handler = IsHungryEvent;
if (handler != null)
{
var e = new HungryEventArgs
{
Message = _hungryMessage
};
handler(this, e);
}
}
}
public class HumanBrain : Brain
{
public HumanBrain()
{
_hungryMessage = "Need food!";
}
}
public class ZombieBrain : Brain
{
public ZombieBrain()
{
_hungryMessage = "Braaaaaains!";
}
}
public class Being
{
protected readonly IBrain _brain;
protected readonly IStomach _stomach;
private readonly string _name;
public Being(string name, IBrain brain, IStomach stomach)
{
_stomach = stomach;
_brain = brain;
_name = name;
_stomach.NeedsFoodEvent += (s, e) =>
{
Console.WriteLine($"{_name}: {e.Message}");
_brain.OnRaiseIsHungryEvent();
};
_brain.IsHungryEvent += (s, e) =>
{
Console.WriteLine($"{_name}: {e.Message}");
};
}
}
}
Some Notes
To provide some output, I faked things in the 2 IStomach implementations. The HumanStomach creates a timer callback in the constructor which fires every 1 second and checks if the current hour is a meal hour. If it is, it raises the NeedsFoodEvent. The ZombieStomach also uses a callback every 1 second, but it just fires the NeedsFoodEvent every time. In a real Unity implementation you'd likely trigger the even based on some event from Unity -- an action the player took, after some preset amount of time, etc.
I'm not quite sure, what you want to do, but it sounds like you want to add triggers to you objects. In my understanding a trigger should be a delegate in this case.
Here an example how to define a delegate-type and add a list of triggers to your Brain-class.
Every brain can now have different triggers. I setup two derived brains to show you how to work with it:
public class TestBrain
{
private static int NextId = 1;
public TestBrain(List<MyTrigger> triggers)
{
this.Triggers = triggers;
this.Id = NextId++;
}
public int Id { get; private set; }
public int Hunger { get; set; }
public int StomachFullness { get; set; }
public List<MyTrigger> Triggers { get; private set; }
public void FireTriggers()
{
foreach (MyTrigger t in this.Triggers)
{
t.Invoke(this);
this.StomachFullness = 100;
}
}
public delegate void MyTrigger(TestBrain b);
}
public class HumanBrain : TestBrain
{
static readonly List<MyTrigger> defaultHumanTriggers = new List<MyTrigger>()
{
b => { if (b.StomachFullness < 50) { b.Hunger = 1; Console.WriteLine("{0} is hungry..", b.Id); } }
};
public HumanBrain() : base(defaultHumanTriggers)
{
}
}
public class RobotBrain : TestBrain
{
static readonly List<MyTrigger> defaultRobotTriggers = new List<MyTrigger>()
{
b => { if (b.StomachFullness < 50) { Console.WriteLine("{0} ignores hunger only want's some oil..", b.Id); } }
};
public RobotBrain() : base(defaultRobotTriggers)
{
}
}
static void Main()
{
// Create some test-data
List<TestBrain> brains = new List<TestBrain>()
{
new HumanBrain(),
new HumanBrain(),
new RobotBrain(),
new HumanBrain(),
};
Console.WriteLine(" - - - Output our Testdata - - -");
foreach (TestBrain b in brains)
{
Console.WriteLine("Status Brain {0} - Stomachfulness: {1} Hunger: {2}", b.Id, b.StomachFullness, b.Hunger);
}
Console.WriteLine(" - - - Empty stomachs - - -");
foreach (TestBrain b in brains)
{
b.StomachFullness = 0;
}
Console.WriteLine(" - - - Fire triggers - - -");
foreach (TestBrain b in brains)
{
b.FireTriggers();
}
Console.WriteLine(" - - - Output our Testdata - - -");
foreach (TestBrain b in brains)
{
Console.WriteLine("Status Brain {0} - Stomachfulness: {1} Hunger: {2}", b.Id, b.StomachFullness, b.Hunger);
}
}

Can I bypass Console.ReadKey() issue when input is redirected?

I am a C# teacher and I wrote some automated HW checker for my students.
The students write C# Console Applications. My HW checker is based on input redirection so I can test their code on my own generated input.
The problem is that students sometimes end their program with a Console.ReadKey() instruction (They do so just to make the execution window not close when they ran the program under F5 - Debug). The Console.ReadKey() crashes when ran under input redirection with the following exception:
System.InvalidOperationException: Cannot read keys when either application does not have a console or when console input has been redirected from a file.
Do I have any way to "bypass" this problem (without altering the students code)? Maybe tell Console to ignore ReadKey instructions?
I see a clear case for a Dependency Injection pattern.
Let's build a simple example, with Read, ReadLine and WriteLine functionalities polymorphically: your students must write a homework in which a number given in the Console.ReadLine() must be parsed as int and returned to the Console Window.
Usually a student writes something like:
class Program
{
static void Main(string[] args)
{
var stringValue = Console.ReadLine();
int number;
if (int.TryParse(stringValue, out number))
Console.WriteLine($"The double of {number} is {number * 2}");
else
Console.WriteLine($"Wrong input! '{stringValue}' is not an integer!");
Console.Read();
}
}
Now, instead, create an interface for the Console functionalities:
public interface IOutput
{
void Read();
string ReadLine();
void WriteLine(string text);
}
A student must create a Homework class that wraps all the required homework code, using an IOutput instance in this way:
public class HomeWork
{
private IOutput _output;
public HomeWork(IOutput output)
{
_output = output;
}
public void Run()
{
_output.WriteLine("Give me an integer:");
var stringValue = _output.ReadLine();
int number;
if (int.TryParse(stringValue, out number))
_output.WriteLine($"The double of {number} is {number * 2}");
else
_output.WriteLine($"Wrong input! '{stringValue}' is not an integer!");
_output.Read();
}
}
The Main becomes:
static void Main(string[] args)
{
var h = new HomeWork(new ConsoleOutput());
h.Run();
}
You give them also the ConsoleOutput class:
public class ConsoleOutput : IOutput
{
public void Read()
{
Console.Read();
}
public string ReadLine()
{
return Console.ReadLine();
}
public void WriteLine(string text)
{
Console.WriteLine(text);
}
}
So the use it instead of call directly Console.Read() etc.
The student must pass to you not the entire Application, but only the Homework class.
You can create a test class that use the Homework class with some test implementations of IOutput like the followings:
public abstract class TestOutput : IOutput
{
public TestOutput()
{
Outputs = new List<string>();
}
public void Read()
{
//do nothing?
}
public abstract string ReadLine();
public void WriteLine(string text)
{
Outputs.Add(text);
}
public List<string> Outputs { get; set; }
}
public class TestOutputWithAValidNumber : TestOutput
{
public TestOutputWithAValidNumber(int value)
{
Value = value;
}
public override string ReadLine()
{
return Value.ToString();
}
public int Value { get; }
}
public class TestOutputWithNotValidNumber : TestOutput
{
public TestOutputWithNotValidNumber(string value)
{
Value = value;
}
public override string ReadLine()
{
return Value;
}
public string Value { get; }
}
The test class can be something like this:
[TestClass]
public class TestOutputClass
{
[TestMethod]
public void TestGoodNumber()
{
var testOutput = new TestOutputWithAValidNumber(1234);
var h = new HomeWork(testOutput);
h.Run();
Assert.AreEqual(1234, testOutput.Value);
Assert.AreEqual("Give me an integer:", testOutput.Outputs[0]);
Assert.AreEqual("The double of 1234 is 2468", testOutput.Outputs[1]);
}
[TestMethod]
public void TestWrongNumber()
{
var testOutput = new TestOutputWithNotValidNumber("foo");
var h = new HomeWork(testOutput);
h.Run();
Assert.AreEqual("foo", testOutput.Value);
Assert.AreEqual("Give me an integer:", testOutput.Outputs[0]);
Assert.AreEqual("Wrong input! 'foo' is not an integer!", testOutput.Outputs[1]);
}
}
If you need only to wrap the Console.Read() method, feel free to simplify all this code, but IMHO I thought that a wider view on this possible solution would have been useful anyway.
If the executables are in IL, you can create an easy application that uses ILDASM.
The key point is: disassemble the executable with ILDASM into a text file/stream, look for any call to Console.Read and remove it, than recompile it and run.

C# Mock a Class With an Internal Property Setter

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

Categories

Resources