创建一个变量,该变量可以存储泛型类型的不同实例,并在变量上调用给定方法,而不管其类型如何

aj.*_*ler 4 c# generics

我正在尝试创建一个通用的模拟运行器.每个模拟都实现了各种接口.最终,它会在运行时通过DLL获取模拟类型,所以我无法事先知道这些类型.

我的密码:

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() {...}
}
Run Code Online (Sandbox Code Playgroud)

我希望我的UI类存储模拟运行器的通用实例(例如

public partial class UI : Window
    {
        SimulationRunner<TSpace,TCell> simulation;
        ...
    }
Run Code Online (Sandbox Code Playgroud)

这样我就可以为它分配不同类型的模拟.例如

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

我想让我的UI控件连接到模拟变量,所以我可以做的事情

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

无论当前绑定到TSpace和TCell的类型是什么,它都能正常工作.

目前我收到错误说"错误10找不到类型或命名空间名称'U'(你错过了使用指令或程序集引用吗?)",对T来说也是如此.

我已经尝试创建一个包装SimulationRunner的控制器类,但我仍然遇到同样的问题,因为我必须在创建它时传入TSpace和TCell的类型,所以问题才会转移到另一个类.

如何在变量中存储任何类型的模拟?如何绑定控件以适用于任何类型的模拟?

Igo*_*aka 6

解决方案是将非泛型方法和属性转换为非泛型接口,以便接口的调用者不必知道类接受哪些类型参数:

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();
  }
}
Run Code Online (Sandbox Code Playgroud)