Dynamically call a function in Windows Form - c#

I'm building an app to test some equipment and the app will have 43 test steps (Step01.cs to Step43.cs). (tests are massive and need to be split in separate files)
In each .cs file there is a public static void Test(){} function.
At any given point the user can go back and redo a test and at the end of each test the user is asked if he wants to redo the next step(only if it has been previously done). If next step has never been done, it continues with the test as usual.
if (currentStep < maxStep )
{
for(int i = currentStep; i < maxStep; i++)
{
_form1.testNumberComboBox.SelectedIndex = i - 1;
if (MessageBox.Show($"{_form1.testNameComboBox.SelectedItem.ToString()} has already been tested.\nWould you like to retest?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
Step02.Test(_form1, sensor);
return;
}
}
_form1.testNumberComboBox.SelectedIndex = maxStep - 1;
}
My question is if it possible to do something like this Step{i}.Test(_form1, sensor); to call what test I need, as I don't really want to do if(i == 2){Step02.Test(_form1, sensor);}...if(i == 40){Step40.Test(_form1, sensor);} if the answer from the user is Yes.
I've done something like this in PHP a while back. Had variables $acc1, $acc2 ... $accX and was able to call them in a for(i) loop with ${"acc$i"}.
I'm not sure if it is possible in C# and that is why I'm asking. (I'm new to C#)

You can use Reflection or use a Dictionary<string, Action>.
Assuming you have test classes like this:
namespace MyTests
{
public class Test1
{
public static void Test() { }
}
}
Call the test using Reflection:
Find the class and the method using reflection and call it:
Assembly.GetExecutingAssembly().GetType("MyTests.Test1")
.GetMethod("Test").Invoke(null, null);
Call the test using Dictionary<string, Action>:
Initialize a Dictionary<string, Action>() like this once:
Dictionary<string, Action> tests = new Dictionary<string, Action>();
tests.Add("Test1", () => Test1.Test());
tests.Add("Test2", () => Test2.Test());
Then call by name whenever you need:
tests["Test1"]();
Combine both reflection and Dictionary<string, Action>:
Or you can combine both for better performance and easier init. Find all test in startup using reflection once:
Dictionary<string, Action> tests = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.FullName.StartsWith("MyTests.Test"))
.Select(t => t.GetMethod("Test"))
.ToDictionary(m => m.DeclaringType.Name,
m => new Action(() => m.Invoke(null, null)));
Run whenever you need:
tests["Test1"]();
tests["Test2"]();

Related

How to run variable number of methods depending on user input in Windows Forms

I am struggling with the concept described below:
User checks x of 5 checkboxes with type of measurements and then he clicks "RUN".
On the "RUN" OnClick() I create a Measure class object.
class Measure
{
string measure_type;
SendCommandToArduino(string nameOfMeasurement)
...
}
I need to run those selected methods IN SEQUENCE (they CANNOT run asynchronous, because they use Serial COM).
I hardcoded something like this:
void Method1()
{
measurement.SendCommandToArduino("tetnienie");
}
void Method2()
{
measurement.SendCommandToArduino("jasnosc");
}
tPomiar1 = new Thread(Method1);
tPomiar1.Start();
tPomiar1.Join();
pomiar.DrawGraphTetnien(tetnienie_Chart);
tPomiar2 = new Thread(Method2);
tPomiar2.Start();
tPomiar2.Join();
MessageBox.Show("Done all measurements!");
No surprise - it worked. But:
I still don't know how to relate number of checked checkboxes with number of methods to run in these threads. Maybe I should hardcode MethodX for all measurements and then run threads from some List list_of_threads?
Threads are overkill for this purpose ( I guess ), cause the longest measurement takes about 10 seconds... Is there any other way?
ThreadPool, Tasks, async/await ? I am totally new to multi-tasking/threading
I also tried something like this, but I didn't finish this solution, it was too hardcore:
List<Thread> list_of_threads= new List<Thread>();
List<Action> measureToDo = new List<Action>();
// link those additions with checkboxes
measureToDo.Add(Method1);
measureToDo.Add(Method2);
measureToDo.Add(Method3);
int i = 0;
foreach (Action action in measureToDo)
{
//substring this one to get method's name!
string methodName = action.Method.Name.ToString());
methodName = methodName.Substring(4,6) // limit of 9 methods here haha
}
foreach (var item in measureToDo )
{
RunThread(item.Method.Name.ToString());
}
void RunThread(Action a)
{
Thread t;
t = new Thread(new ThreadStart(a.Method.Name)).Start();
}
For a measure_type I created a '5-bit' string -> Containg "1" if the checkbox on this position was checked.
"01000" / "10011" etc.
Thank You in advance for all hints/tips! :)
Perhaps you are overcomplicating things, and a simple solution would be perfectly well.
You can use Control.Tag property and add the name (as string) of the measure to everyone of your checkboxes. Then, you can enumerate your check-boxes, see which is checked, and get a list of strings with the names of the measures you need to perform.
Then, you need a single method to execute your measures. It should enumerate the list, and have a switch to map a measure to a method:
void ExecuteMeasures(List<string> measures)
{
foreach (string measure in measures)
{
switch (measure)
{
case "Measure 1": MeasureMethodOne(); break;
// and so on...
}
}
}
Then you don't need to run each measure method in a separate thread, because you want them to be executed sequentially. You only need to run the ExecuteMeasureMethod in a separate thread. Having it run for seconds, a separate thread is fine. Still, to keep things neat, use a long running task:
var listOfMeasures = new List<string>();
//Populate your list from the selection of check boxes
Task t = Task.StartNew ( ()=> ExecuteMeasures(listOfMeasures), TaskCreationOptions.LongRunning);
await t;
Here is my solution:
1. Define a Action array to store your methods
2. Get the values of checked items(checkbox1's value is 0, etc.) as the array indices
3. Invoke the relevant method in the array.
Codes are something like :
public static void Main()
{
Action[] actions = new Action[5];
actions[0] = Method1;
actions[1] = Method2;
string checkedValue = "1";
actions[int.Parse(checkedValue) - 1].Invoke();
}
static void Method1()
{
Console.WriteLine(1);
}
static void Method2()
{ }
Or you can simplify the code as below:
public static void Main()
{
Action[] actions = new Action[5];
actions[0] = ()=> { Console.WriteLine(1); };
actions[1] = ()=> { Console.WriteLine(2); };
string checkedValue = "1";
actions[int.Parse(checkedValue) - 1].Invoke();
}

How to call functions from data structure?

I would like to be able to describe some actions as function calls represented in a datastructure. Then I would like to be able to loop through the data structure and call the functions.
This pseudo-code describes what I would like to achieve:
static void Main(string[] args)
{
Action[] actions = new Action[]
{
new Action(DoAction1(5)),
new Action(DoAction1(7)),
new Action(DoAction2("100201")),
};
foreach (Action action in actions)
{
action.<Run the action function>;
}
}
public static void DoAction1(int x)
{
}
public static void DoAction2(string x)
{
}
It kind of looks like delegates, but not quite.
Any ideas on how to achieve this?
This is what you're looking for?
Action[] actions = new Action[]
{
new Action(()=>DoAction1(5)),
new Action(()=>DoAction1(7)),
new Action(()=>DoAction2("100201"))
};
foreach (Action action in actions)
{
action();
}
The Action class in .net allows you to directly assign lambdas
var actions = new List<Action>
{
() => DoAction1(5),
() => DoAction1(7),
() => DoAction2("100201"),
};
then executing an array of actions can be done like :-
actions.ForEach(a => a());
then you can add more actions to the list
actions.Add(() => DoAction2("blah blah"));
may be you can use reflection
var methodNames = typeof(MyType).GetMethods(BindingFlags.Public |
BindingFlags.Static)
.Select(x => x.Name)
.Distinct()
.OrderBy(x => x);
OR
foreach (var property in yourObject.GetType().GetProperties())
{
if (property.PropertyType.GetInterfaces().Contains(typeof(IEnumerable)))
{
foreach (var item in (IEnumerable)property.GetValue(yourObject, null))
{
//do stuff
}
}
}
Since you seem not to want to use the Action class, you can check out the SharpByte codebase, specifically the SharpByte.Dynamic namespace. It allows evaluating statements and executing scripts with just a single method call, like this:
someContextObject.Execute("[executable code here]");
However, you can use it another way which may be what you're looking for. When you execute one of those dynamic compilation/execution extension methods, here's what's actually happening (paraphrased):
IExecutable executable = ExecutableFactory.Default.GetExecutable(ExecutableType.Script, "[source code here]", optionalListOfParameterNames, optionalListOfNamespaces);
If you wanted to evaluate an expression/function instead of run multiple-lined statements, you'd use ExecutableType.Expression . The main point is that you can keep a reference around to an IExecutable object and run it as many times as you like, passing different parameter values each time. You can also copy IExecutable objects freely using the .Copy() method of each; they are designed to be thread-safe but lightweight, and references or copies could thus be placed in a data structure for further (re)use. This post explains a bit more.

FakeItEasy Action parameter in UnitTest, but still execute inner Action code

I'm currently making some UnitTests for some new features I've added to our ASP.NET project (no it's not test-driving design). We use the NHibernate framework and use the UnitTest Mock-ing library FakeItEasy.
I have the following class & method which I want to test:
public class Round
{
public static Round Create(List<Company> activeCompanies, Period period,
BusinessUser user, BusinessUser systemUser,
ISession session, IEntityQuery entityQuery,
RoundProcessBuilder processBuilder)
{
var round = new Round
{
Processes = new List<Process>();
Period = period,
CreationDate = DateTime.Now,
CreatedBy = user
};
// Save the Round in the DB so we can use it's Id in the Processes:
session.Save(round);
foreach (var company in activeCompanies)
{
var companyData = session.Get<CompanyData>(company.Id);
var processResult =
roundProcessBuilder.Build(
systemUser,
new CreateRoundProcessData(company, round, companyData),
entityQuery,
session);
processResult.HandleProcess(process =>
{
// serviceBus can stay null
process.Create(systemUser, DateTime.Now, session, null);
// No need to save the session here. If something went
// wrong we don't want halve of the processes being saved
round.Processes.Add(process);
// It's all or nothing
});
}
return round;
}
}
What I mainly want to test: When I use this Round#Create method with let's say 100 active companies, it should create 100 processes, and each of those processes should contain the RoundId.
This is my UnitTest so far:
[TestFixture]
public class RoundTest
{
private BusinessUser _systemUser;
private DateTime _creationDateRound1;
private List<Company> _activeCompanies;
private RoundProcessBuilder _roundProcessBuilder;
private ISession _session;
[SetUp]
public void Setup()
{
_creationDateRound1 = new DateTime(2015, 10, 5);
_systemUser = TestHelper.CreateBusinessUser(Role.Create("systemuser", "test",
Int32.MaxValue));
_activeCompanies = new List<Company>
{
TestHelper.CreateCompany();
};
_roundProcessBuilder = A.Fake<RoundProcessBuilder>();
_session = A.Fake<ISession>();
}
[Test]
public void TestCreateRoundWithoutPreviousRound()
{
var fakeExpectedRound = Round.Create(_activeCompanies, DateTime.Now.ToPeriod(),
_systemUser, _systemUser, _session, null, _roundProcessBuilder);
var fakeExpectedRoundData = RoundProcessData.Create(TestHelper.CreateCompany(),
fakeExpectedRound, new CompanyData());
var fakeExpectedProcess = new Process(_systemUser, null, "processName", null,
fakeExpectedRoundData, "controllerName", null);
var processSuccessResult = new ProcessSuccessResult(fakeExpectedProcess);
A.CallTo(() => _roundProcessBuilder.Build(null, null, null, null))
.WithAnyArguments()
.Returns(processSuccessResult);
A.CallTo(() => processSuccessResult.HandleProcess(A<Action<Process>>.Ignored))
.Invokes((Action<Process> action) => action(fakeExpectedProcess));
var round = Round.Create(_activeCompanies, _ceationDateRound1.ToPeriod(),
_systemUser, _systemUser, _session, null, _roundProcessBuilder);
Assert.AreEqual(_activeCompanies.Count, round.Processes.Count, "Number of processes");
Assert.AreEqual(round.Period.Quarter, Math.Ceiling(_creationDateRound1.Month / 3.0m), "Quarter");
Assert.AreEqual(round.Period.Year, round.Year, "Year");
// Test if each of the processes knows the RoundId, have the proper state,
// and are assigned to the systemuser
//foreach (var process in round.Processes)
//{
// var roundProcessData = process.ProcessData as RoundProcessData;
// Assert.IsNotNull(roundProcessData, "All processes should have RoundProcessData-objects as their data-object");
// Assert.AreEqual(roundProcessData.Round.Id, round.Id, "RoundId");
// Assert.AreEqual(process.Phase.State, PhaseState.Start, "Process state should be Start");
// Assert.AreEqual(process.AssignedTo, _systemUser, "AssignedTo should be systemuser");
//}
}
... // More tests
}
My problem lies in the following code:
A.CallTo(() => processSuccessResult.HandleProcess(A<Action<Process>>.Ignored))
.Invokes((Action<Process> action) => action(fakeExpectedProcess));
It gives an "The specified object is not recognized as a fake object." error.
The reason I have this part of the code is because the process in the following part was null without it:
processResult.HandleProcess(process => // <- this was null
{
process.Create(systemUser, DateTime.Now, session, null);
round.Processes.Add(process);
});
PS: I uncommented the foreach with additional checks in my UnitTest because it most likely is pretty useless anyway when I mock the process itself.. My main test is if processes are created and added to the list based on the active companies given.
Your problem seems to be that you are trying to add "fake" logic to an object that is not in fact, a fake:
// You create this as an instance of ProcessSuccessResult:
var processSuccessResult = new ProcessSuccessResult(fakeExpectedProcess);
...then proceed to attempt to add a condition to it here:
A.CallTo(() =>
processSuccessResult
.HandleProcess(A<Action<Process>>.Ignored))
.Invokes((Action<Process> action) => action(fakeExpectedProcess));
In order to do this last bit, the variable processSuccessResult will need to be a fake instance of an interface, so that FakeItEasy can work with it, and apply the logic you want.
I'm assuming ProcessSuccessResult is a class you have access to, and are able to edit? If so, you should be able to add an interface to it, that will contain the methods you need, so you can work against that later.
Once you've defined that, you should be able to create your fake object as follows, where IProcessSuccessResult will be a fake implementation of your interface, provided by FakeItEasy:
var processSuccessResult = A.Fake<IProcessSuccessResult>();
Now you should be able to add logic to that fake object using A.CallTo(...).
Of course, this will imply that the real implementation of your class ProcessSuccessResult is not included or called via the variable processSuccessResult. If part of it needs to be, then you might try to either:
Add logic similar to it, or calls to it from the fake object using FakeItEasy's set up code (although this might get overly complicated), OR:
Add a separate variable to contain an instance of the real class (i.e. two variables fakeProcessSuccessResult and processSuccessResult, respectively), and use separate tests for testing separate aspects of your both this class, and it's usages.
I would recommend the latter, if possible.
I hope this is clear enough, and that this will be useful to you. I know it can be quite complicated sometimes, to find the optimal strategy for testing things like this.

Is there anyway to detect what will be called from a method?

In C#, when I call a method, I want to be able to detect if it will (or could potentially) call something with a certain attribute.
For example, when, TheProgram.Run() get's called, I want to know that it will call a MyClass.DoTheWork, which has an attribute [IsRegistered], which calls a private method FormatTheResult() which also has the attribute [IsRegistered].
I've been thinking about it for a while and can't think how it could be achieved. I'm thinking, something like the invert of a stack trace, or registering components with an attribute or aspect, or perhaps leaning on MEF.
Is this possible?
This detection could happen at compile time or a run time, but ideally before the method with the attribute is executed.
Mocking frameworks can do this. It is useful for behavioural tests.
For example, given this setup:
public class Calculator {
private IHelpers _helperMethods;
public Calculator(IHelpers helper) {
_helperMethods = helper;
}
public int Add(int a, int b) {
if (_helperMethods.AboveZero(a) && _helperMethods.AboveZero(b)) {
return a + b;
}
throw new Exception("Argument not above zero");
}
}
public interface IHelpers {
bool AboveZero(int i);
}
Using Moq, you can verify (via a behavioural unit test) that IHelpers.AboveZero is called when calling the Add method like so:
[TestMethod]
public void When_Add_Called_Verify_AboveZero_Called_Too() {
// Arrange
var helperMock = new Mock<IHelpers>();
helperMock.Setup(x => x.AboveZero(It.IsAny<int>())).Returns(true);
var calc = new Calculator(helperMock.Object);
// Act
var result = calc.Add(1, 2);
// Assert
helperMock.Verify(x => x.AboveZero(It.IsAny<int>())); // verify that AboveZero was called.
}
The attributes are a different story though..
Is this what you were after?
(Please excuse any compiler errors.. this was typed by hand :/)
What you are probably looking for is Roslyn.
http://msdn.microsoft.com/en-au/vstudio/roslyn.aspx
What you can do with this is analize the syntax tree directly, so for your method in question you could access from the syntax tree all method calls that occur. Then you can follow that and check the method being called has that attribute.
Is pretty complex stuff, so I wont attempt a code sample for your particular scenario but I have used it before to analize multiple solitions and inject code.
It's pretty awesome here is a sample from the docs.
namespace GettingStartedCS
{
    class Program
    {
        static void Main(string[] args)
        {
            SyntaxTree tree = SyntaxTree.ParseCompilationUnit(
#"using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(""Hello, World!"");
        }
    }
}");
            var root = (CompilationUnitSyntax)tree.GetRoot();
            var firstMember = root.Members[0];
            var helloWorldDeclaration = (NamespaceDeclarationSyntax)firstMember;
            var programDeclaration = (TypeDeclarationSyntax)helloWorldDeclaration.Members[0];
 
            var mainDeclaration = (MethodDeclarationSyntax)programDeclaration.Members[0];
 
            var argsParameter = mainDeclaration.ParameterList.Parameters[0];
        }
    }
}
Resharper does kind of what you want. Execute the menu command Resharper -> Inspect -> Outgoing calls, and then expand tree nodes ad infinitum until you reach the desired method. If you're using reflection or stuff like that, you're out of luck, I guess. The picture below is an example of how it works.
This is the way I've found to do it:
public static IList<MethodBase> GetCalledMethods(MethodBase methodBase)
{
IList<MethodBase> calledMethods = new List<MethodBase>();
var body = methodBase.GetMethodBody();
Module module = Assembly.GetExecutingAssembly().ManifestModule;
byte[] bytes = body.GetILAsByteArray();
using (var stream = new MemoryStream(bytes))
{
long streamLength = stream.Length;
using (var reader = new BinaryReader(stream))
{
while (reader.BaseStream.Position < streamLength)
{
byte instruction = reader.ReadByte();
if (instruction == OpCodes.Call.Value
|| instruction == OpCodes.Callvirt.Value
|| instruction == OpCodes.Newobj.Value)
{
int token = reader.ReadInt32();
var method = module.ResolveMethod(token);
calledMethods.Add(method);
}
}
}
}
return calledMethods;
}

How to calculate the number of instance created between two checkpoint

I would like to do something like :
ObjectRecorder.Start();
//Do stuff here ...
ObjectRecorder.Stop();
//And get the result
List<Object> result = ObjectRecorder.GetAll();
//or even
ObjectRecorder.GetNumberInstanceCreated();
What I am trying to achieve
I am using a BlockingCollection and profiling my application I saw that the TryTake is creating object internaly. As I am calling this method really often, I would like to expose the bug with a unit test and then implementing a new ImprovedBlockingQueue and seeing that the problem is solved.
Any ideas?
What are you trying to achieve is extremely hard to achieve because you would like to inspect managed memory of the process while it is running. Such operation can be very costly and I really think a different approach to such unit test should be taken, for example you can try to to use GC.GetTotalMemory method to track overall memory usage. In case of isolated unit test it might be enough.
Nevertheless, I would like to mention a possibility to achieve what you want with help of astonishing Microsoft.Diagnostics.Runtime library (which is in pre-release phase). You can attach to your running process and inspect Managed Heap like that:
public static void GetStats(ClrRuntime runtime)
{
ClrHeap heap = runtime.GetHeap();
var stats = heap.EnumerateObjects()
.Select(obj => new
{
Type = heap.GetObjectType(obj),
ObjectAddress = obj
})
.GroupBy(g => g.Type,
g => g.Type.GetSize(g.ObjectAddress))
.Select(gr => new
{
Name = gr.Key.Name,
Count = gr.Count(),
Size = gr.Sum(x => (int)x)
})
.Where(t => !t.Name.StartsWith("System.") &&
!t.Name.StartsWith("Microsoft.") &&
!t.Name.Equals("Free"))
.ToList();
Console.WriteLine("---------- Start ----------");
foreach (var item in stats)
Console.WriteLine("{0} {} {2}", item.Size, item.Count, item.Name);
}
with sample usage:
var process = Process.GetCurrentProcess();
using (var dataTarget = DataTarget.AttachToProcess(process.Id, 1000, AttachFlag.Passive))
{
string dacLocation = dataTarget.ClrVersions[0].TryGetDacLocation();
ClrRuntime runtime = dataTarget.CreateRuntime(dacLocation);
GetStats(runtime);
List<User> list = new List<User>();
Enumerable.Range(1, 1000).ToList().ForEach(i => list.Add(new User() { Age = i }));
Thread.Sleep(10000);
GetStats(runtime);
}
BUT: For attaching to itself, only AttachFlag.Passive is possible which is described as:
Performs a "passive" attach, meaning no debugger is actually attached
to the target process. The process is not paused, so queries for
quickly changing data (such as the contents of the GC heap or
callstacks) will be highly inconsistent** unless the user pauses the
process through other means.
Hence it might be hard to have a deterministic stats about Managed Heap in such case.
This may helps:
class ObjectRecorder
{
static List<ObjectRecorder> valuse=new List<ObjectRecorder>();
bool record = false;
public ObjectRecorder()
{
//your code
if (record){ valuse.Add(this); }
}
public void StartRecording(){ record = true; }
public void StopRecording(){ record = false; }
public void ResetRecording()
{
valuse = new List<ObjectRecorder>();
}
public List<ObjectRecorder> GetAll()
{
return valuse;
}
}

Categories

Resources