使用动态代码处理大量数据

时间:2014-12-19 15:25:31

标签: c# .net appdomain dynamic-code

我希望能够动态地更改游戏代码。例如,假设我的游戏以这种方式构建:

class GameState {
    public int SomeData;
    public Entity[] EntityPool;
}

interface IServices {
    IRenderer Renderer { get; }
}

interface IGameCode {
    void RenderAndUpdate(GameState currentState, IServices serviceProvider);
}

我现在希望能够编写这样的代码:

 void MainLoop() {
    IGameCode gameCode = new DefaultGameCode();
    while(true) {
       // Handle Plattform things
       if(shouldUseNewGameCode) {
          UnloadCode(gameCode);

          gameCode = LoadCode("new.dll");
          // or
          gameCode = LoadCode("new.cs");
       }
       // Call GameTick
       gameCode.RenderAndUpdate(gameState, services);
    }
 }

我已经使用过AppDomains和一个Proxyclass,但是每个帧序列化太慢了。我试图只传递一个指针,但由于AppDomains使用自己的虚拟地址空间,我无法访问GameState对象。我的另一个想法是使用Reflection通过GetMethodBody()从编译的方法中获取IL并将其传递给DynamicMethod,但这会限制我编写RenderAndUpdate方法的方式,因为我不能在IGameCode实现中使用Submethods或Variables

那么我怎样才能实现我想做的事呢?

1 个答案:

答案 0 :(得分:0)

正如您所见,您真的不希望在每个帧上越过AppDomain边界,特别是如果该代码必须回调到主代码,例如IServices多次。即使使用MarshalByRefObject,这可以改善一些事情,但它会变得太慢。因此,您需要一个不涉及AppDomain的解决方案。

你的装配有多大?您希望多久改变一次?

注意到.NET程序集通常具有相当大的空间效率,并且在您的场景中,用户似乎不太可能在会话中多次切换程序集,我只会将您的DLL作为{{1}读入内存然后使用Assembly.Load(byte[]);加载它。

或者,如果您真的无法容忍进程内存空间中的死组件,我认为最好使用辅助进程,即“launcher”:当您想要切换实现时,启动辅助进程(或者只是让它一直运行,如果你想要的话),然后等待当前的游戏进程退出,然后用新的设置启动一个新的。

切换速度较慢,但​​当然每个开关只需一次性费用,然后程序可以在实际游戏过程中全速运行。