相关疑难解决方法(0)

在没有AppDomains的情况下运行时重新编译C#

假设我有两个C#应用程序 - game.exe(XNA,需要支持Xbox 360)和editor.exe(在WinForms中托管的XNA) - 它们共享一个engine.dll可以完成绝大部分工作的程序集.

现在让我们说我想添加一些基于C#的脚本(它不是"脚本",但我会称之为).每个级别都有自己继承自基类的类(我们称之为LevelController).

这些是这些脚本的重要约束:

  1. 它们需要是真实的,编译好的C#代码

  2. 他们应该需要最少的手动"粘合"工作,如果有的话

  3. 它们必须与其他所有内容在同一个AppDomain中运行

对于游戏 - 这非常简单:所有脚本类都可以编译成一个程序集(比如说levels.dll),并且可以根据需要使用反射来实例化各个类.

编辑要困难得多.编辑器能够在编辑器窗口中"玩游戏",然后将所有内容重置回原来的位置(这就是编辑器首先需要了解这些脚本的原因).

我想要实现的基本上是编辑器中的"重新加载脚本"按钮,它将重新编译并加载与正在编辑的级别相关联的脚本类,当用户按下"播放"按钮时,创建最近的实例编译脚本.

其结果将是编辑器中的快速编辑测试工作流程(而不是替代方案 - 保存级别,关闭编辑器,重新编译解决方案,启动编辑器,加载级别,测试).


现在我我已经找到了实现这个目标的潜在方法 - 这本身就会产生一些问题(如下所示):

  1. .cs将给定级别(或者,如果需要,整个levels.dll项目)所需的文件集合编译为临时的,唯一命名的程序集.那个集会需要参考engine.dll.如何在运行时以这种方式调用编译器?如何让它输出这样的程序集(我可以在内存中执行)吗?

  2. 加载新装配.我在同一个进程中加载​​具有相同名称的类是否重要?(我的印象是名称是由程序集名称限定的?)

    现在,正如我所提到的,我无法使用AppDomains.但是,另一方面,我不介意泄漏旧版本的脚本类,因此卸载的能力并不重要.除非是吗?我假设加载可能几百个组件是可行的.

  3. 在播放关卡时,实例是从刚加载的特定程序集继承自LevelController的类.这该怎么做?

最后:

这是一种明智的做法吗?它可以做得更好吗?


更新:这些天我使用一种更简单的方法来解决潜在的问题.

c# compilation assembly.load

20
推荐指数
1
解决办法
6341
查看次数

罗斯林启动时间慢

我注意到Roslyn解析/编译的启动时间是一个相当重要的一次性成本.编辑:我正在使用Roslyn CTP MSI(程序集在GAC中).这是预期的吗?有没有解决方法?

运行下面的代码与1次迭代(约3秒)和300次迭代(约3秒)的时间几乎相同.

[Test]
public void Test()
{
    var iters = 300;
    foreach (var i in Enumerable.Range(0, iters))
    {
        // Parse the source file using Roslyn
        SyntaxTree syntaxTree = SyntaxTree.ParseText(@"public class Foo" + i + @" { public void Exec() { } }");

        // Add all the references we need for the compilation
        var references = new List<MetadataReference>();
        references.Add(new MetadataFileReference(typeof(int).Assembly.Location));

        var compilationOptions = new CompilationOptions(outputKind: OutputKind.DynamicallyLinkedLibrary);

        // Note: using a fixed assembly name, which doesn't matter as long as …
Run Code Online (Sandbox Code Playgroud)

c# roslyn

5
推荐指数
1
解决办法
1847
查看次数

使用Roslyn RC发送到DynamicAssembly

从编译Roslyn SyntaxTree的许多示例中,我看到了以下代码:

[... create tree and compilation ...]
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("foo"), AssemblyBuilderAccess.RunAndCollect);
var module = assembly.DefineDynamicModule("foo");

var result = compilation.Emit(module);
Run Code Online (Sandbox Code Playgroud)

但是当我尝试在当前使用Visual Studio 2015 RC发布的Roslyn中执行此操作时,我看到没有Emit()哪个需要一个模块.我需要写入流并将其加载到常规AppDomain锁定中Assembly.

然后我从Tomas Matousek看到这个答案:https://stackoverflow.com/a/22977158

他说这已被删除,因为它"有问题".

我很难在互联网上找到关于此的任何其他信息.有谁知道:

  • 在Roslyn中还有另一种方法可以编译成可以进行垃圾回收的程序集吗?
  • 或者这将在VS/Roslyn的最终版本中得到支持?
  • 如果这里没有人知道(无法找到正式的,积极的罗斯林论坛),我应该在哪里指导这个问题?

c# roslyn

5
推荐指数
1
解决办法
335
查看次数

标签 统计

c# ×3

roslyn ×2

assembly.load ×1

compilation ×1