在调用在运行时编译的代码时,如何访问当前应用程序中的对象?

时间:2012-12-12 05:18:16

标签: c# .net csharpcodeprovider

我当前的项目是一个应用程序,它允许您使用C#编写代码,然后使用CSharpCodeProvider执行它。只要代码本身就是一个完整的应用程序,它就可以正常工作,例如:

using System;

namespace RuntimeCode {
    public static class Program {
        public static void Main() {
            Console.WriteLine("Hello, world!");
        }
    }
}

然后,应用程序使用CompileAssemblyFromSourceGenerateInMemory = true编译给定代码,然后在编译的程序集中调用Main方法。

我的问题是,如何让编译的代码访问主应用程序中的对象?

3 个答案:

答案 0 :(得分:1)

请注意,运行时生成的代码正在作为单独的进程执行。因此,您需要在主要应用程序和新创建的应用程序之间执行跨进程通信。

实现跨进程或跨域通信的一种好方法是在主应用程序或默认应用程序域中托管特殊服务。由此产生的组件将成为客户。

我建议使用WCF和NetNamedPipeBinding。您只需要配置合同和端点。


另请注意,GenerateInMemory=true控制的唯一方法是加载从磁盘到内存的结果程序集。那就是它。


如果您将脚本加载到默认的AppDomain中,那还是一块蛋糕。只需创建一个静态成员:

namespace MyNamespace
{
    public class Core
    {
        public static Core Instance { get; set; }
    }
}

并按完整类型名称访问它:

MyNamespace.Core.Instance;

答案 1 :(得分:0)

  

然后,应用程序编译给定的代码[...],然后在编译的程序集中调用Main方法。

我认为这几乎可以回答你的问题。您编译的代码没有理由必须使用无参数Main()方法。例如,如果您需要访问的方法位于IHost界面中,那么您可以要求脚本使用Main方法,其参数类型为IHost。然后,您将调用它,传入IHost的当前实例。

答案 2 :(得分:0)

您注入的代码无法访问主应用程序中定义的类和对象。(要访问主应用程序中定义的类,您可以再次使用注入代码中的反射,但对象不可访问。)

但您只需将数据作为参数发送到注入的代码:

using System;

namespace RuntimeCode {
    public static class Program {
        public static void StartPoint(object obj) {
            Console.WriteLine("Hello, world!");
        }
    }
}

然后通过发送包含所需数据的StartPoint对象来调用obj方法。

您可以使用您需要的任何类型的对象。但它应该通过注入代码来识别。