Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a variable that can store different instances of generic types and calling a given method on the variable, regardless of the type

Tags:

c#

generics

I am trying to create a generic simulation runner. Each simulation implements a variety of interfaces. Eventually, it will pick up simulation types via DLLs at run time, so I will have no way of knowing the types beforehand.

My Currrent Code:

public class SimulationRunner<TSpace, TCell>
    where TSpace : I2DState<TCell>
    where TCell : Cell
{
    public TSpace InitialState { get; set; }
    public IStepAlgorithm<TSpace,TCell> StepAlgorithm { get; set; }
    public IDisplayStateAlgorithm<TSpace,TCell> DisplayStateAlgorithm { get; set; }
    public int MaxStepCount { get; set; }
    ...
    public void Run() {...}
    public void Step() {...}
    public void Stop() {...}
}

I want my UI class to store a generic instance of the simulation runner (Eg

public partial class UI : Window
    {
        SimulationRunner<TSpace,TCell> simulation;
        ...
    }

so that i can assign different types of simulations to it. Eg

simulation = new SimulationRunner<2DSpace, SimpleCell>(); 
// do stuff
// start new simulation of different type 
simulation = new SimulationRunner<3DSpace, ComplexCell>();

I want to have my UI controls wired to the simulation variable so i can do things like

private void mnuiSimulate_Click(object sender, RoutedEventArgs e)
{
    if (simulation != null) simulation.RunSimulation();
}

and have it work regardless of what types are currently bound to TSpace and TCell.

Currently I am getting errors saying "Error 10 The type or namespace name 'U' could not be found (are you missing a using directive or an assembly reference?)", and the same again for T.

I have tried creating a controller class that wraps the SimulationRunner, but I still have the same problem in that I have to pass in the types of TSpace and TCell when I create it, so the problem just gets moved to a different class.

How can I store any type of simulation in a variable? How can I bind the controls to work on any type of simulation?

like image 938
aj.esler Avatar asked Jan 22 '23 15:01

aj.esler


1 Answers

The solution is to take the non-generic methods and properties into a non-generic interface, so that the caller of the interface doesn't have to know which type parameters the class accepts:

public interface ISimulationRunner {
    public int MaxStepCount { get; set; }
    ...
    public void Run() {...}
    public void Step() {...}
    public void Stop() {...}
}

public class SimulationRunner<TSpace, TCell> : ISimulationRunner 
    where TSpace : I2DState<TCell>
    where TCell : Cell
{
    public TSpace InitialState { get; set; }
    public IStepAlgorithm<TSpace,TCell> StepAlgorithm { get; set; }
    public IDisplayStateAlgorithm<TSpace,TCell> DisplayStateAlgorithm { get; set; }
}

public partial class UI : Window
{
  ISimulationRunner simulation = new SimulationRunner<2DSpace, SimpleCell>();
  private void mnuiSimulate_Click(object sender, RoutedEventArgs e)
  {
    if (simulation != null) simulation.RunSimulation();
  }
}
like image 102
Igor Zevaka Avatar answered Feb 16 '23 02:02

Igor Zevaka