我有一个应用程序,我必须为用户提供实时可扩展性。你可以把它看作一种计算引擎,有很多数据和一些数学/数字算法。我提供了一些静态字段(数据)和方法(计算),用户可以使用这些字段和方法构建一个应该返回双精度的有效C#表达式。
用户在文本框中键入有效的表达式,我应该提供结果。我目前所做的是在内存中生成的程序集的静态方法上注入表达式,步骤如下http://blogs.msdn.com/b/abhinaba/archive/2006/02/09/528416.aspx.然后,我使用反射来调用特定的方法并返回结果。
除了生成的程序集在应用程序的整个生命周期中不断累积之外,这种方法运行良好。当我只有客户端应用程序时,这还可以,但现在我正在转向基于服务器的应用程序,我不想不时地重置服务。
在搜索如何卸载程序集时,我发现了System.Addin命名空间。它做的正是我想要的:将程序集加载到另一个AppDomain上,我可以丢弃后者。它甚至封装了所有反射。
我现在遇到的唯一问题是AddInStore需要一个文件路径,但通过将CompileParameters的GenerateInMemory属性设置为true,我的所有程序集都是在内存中生成的。是否绝对需要将程序集写入磁盘?或者可以将运行时编译的程序集直接用作外接程序吗?
谨致问候,Carlos
我不明白你用AddInStore做什么(卸载程序集?),但你可以卸载appdomain(你说你可以在其中创建动态加载的程序集):
AppDomain.Unload(yourAppDomain);
或者你可能面临着一个更大的问题!
也许DynamicMethod就是您想要的。
如果没有,那么您可以看看IronPython。它很容易添加到您的应用程序中,而且功能强大。当然,这将比编译的C#代码慢,但我不确定它是否会比编译+反射慢。
你当然可以做MZN提到的。你可以:
- 将编译器类更改为从MarshalByRefObj派生。这是CLR创建代理对象所必需的。你将不得不检查一下.网络远程处理。不过也不算太多
- 创建您自己的AppDomain
- 最后调用CreateInstanceFromAndUnwrap的重载之一,在新的AppDomain上加载带有编译器类的assmebly,并在其上创建编译器的实例。它将返回代理对象。然后使用代理对象进行实际编译。已编译的程序集将加载到新的AppDomain上。当您决定不再需要此程序集时,或者当已达到编译程序集的最大数量时,您可以进行MZN提到的调用,并卸载AppDomain和所有加载的程序集。然后从新的AppDomain中再次重复整个过程
我认为最简单的方法是使用IronPython。
目前,我正在开发一个基于MAF的应用程序,其中包括现场编译C#代码(使用System.CodeDom)。它与您的类似,但在我的情况下,编译只在升级后进行。因此,我对加载的许多"脚本"程序集没有问题。此外,我还在文件系统上构建程序集。
问候并祝你好运,
Panos