C#编译器结果生成内存?

C#编译器结果生成内存?,c#,.net-assembly,C#,.net Assembly,我一直在关注这个。这是我能找到的最接近的东西,但不完全是 在我提问之前,让我解释一下我的最终目标是什么,我正在制作一个支持web的编译器平台,正因为如此,我想在内存中做所有事情(不生成文件),所以我想能够编译代码,然后能够引用我刚刚编译的类中的对象进行任意测试。我知道这听起来有多不安全,所以欢迎您提供有关安全性的信息 我的问题是如何将C#源代码编译到内存中,并创建该类的实例? 目前,我正在着手生成有效的.dll并在VisualStudio中手动导入和使用它 我接下来的两个步骤是: 自动加载程序

我一直在关注这个。这是我能找到的最接近的东西,但不完全是

在我提问之前,让我解释一下我的最终目标是什么,我正在制作一个支持web的编译器平台,正因为如此,我想在内存中做所有事情(不生成文件),所以我想能够编译代码,然后能够引用我刚刚编译的类中的对象进行任意测试。我知道这听起来有多不安全,所以欢迎您提供有关安全性的信息

我的问题是如何将C#源代码编译到内存中,并创建该类的实例?

目前,我正在着手生成有效的.dll并在VisualStudio中手动导入和使用它

我接下来的两个步骤是:

  • 自动加载程序集(这是我在这里要求的)
    • 这意味着我不再需要给出dll的路径,也不需要手动获取封闭类成员的地址
  • 任意引用它的成员
    • 这意味着我可以创建一个类的接口,而不需要知道它的成员,就像foreach循环如何在键值对上工作一样
为了完全记住这一点,我已经试过了。(来源和解释)

最后,在代码的这一点上,我希望返回一些我可以调用的属性的对象。 因此调用
objectobj=newsourcetoobj(source.class()或其他可能的事情

沿着这条路走下去,这可能确实是一条错误的路,这给我留下了3个未知数

  • 什么是
    System.Security.Policy.Security
    对象。
  • AppDomain.CreateInstanceAndUnwrap()的正确参数是什么
  • 那么如何将其作为对象返回?
当然,这种方法可能是错误的,它是基于上面的链接,这是密切的,但没有土耳其


编辑:经过更多的研究,我想包括一个源文件的例子

namespace testNS {
  public partial class i18Rule {
     private string i18_Name;
     private string i18_Value;
     public void setName(string s) {
         i18_name = s;
     }
     /* Other obvious functions */
  };
};

我相信我取得了一点进步,接着我的问题的第二条,如何创建一个实例

我继续使用AppDomain来包含我的程序集。我还采用了写入磁盘并在字节数组中读取的方法,就像我遇到的这个问题一样

如何将C#源代码编译到内存中,并创建该类的实例

当我想将源代码作为输入并编译和执行它时,我遇到了类似的问题。这是我在阅读后得出的结论:

所以把它放在一起

   public void Example(){
       dynamic instance = 
            CompileSource("namespace Test{public class DynamicCompile{ /*method*/}}")
            .TryLoadCompiledType("Test.DynamicCompile");

        //can now call methods on 'instance'
   }

GenerateInMemory属性是一种错觉,目前没有运行在进程中的CodeDom编译器。您总是会得到一个文件,当您设置GenerateInMemory=true时,它会自动加载。如果你想将代码加载到另一个appdomain中,就不要使用它。哦,天哪,这太令人不安了。我想我会修改一个替代方案。你为什么要尝试加载一个新的AppDomain?您需要稍后卸载它吗?我可能会被误导使用AppDomain,因此据我所知,它提供了一层隔离。这对我来说意味着。。。1.假设我正在远程编译和运行的代码想要读取一个文件,我想要应用一个安全策略,说明哪些文件是可以的。2.我不想有人写“突围”代码。所以我想我相信这是一个沙箱。这都是很早的事情。更多的概念证明,而不是工作模型。我可以完全不用它。我一直在看这个,顺便说一句。它看起来很像我开始的步骤。这意味着我已经能够做到这一点,当我有先兆知识。这是在任意C#源上进行的,并且不创建文件,这似乎是不可避免的,这很好。我已经看过了,谢谢你的回答。
Activator.CreateInstance(类型,构造函数args)看起来像我接下来想要的。是的,你很接近。
Activator
将实际创建
类型的实例
,您可以使用
dynamic
对返回的实例调用方法。例如,如果您知道源类实现了一个接口,那么可以调用这些方法。当然可以使用反射。如果有帮助,下面是我完整的CompilerResult扩展类。它有助手方法来调用使用反射的方法:这肯定会引导我走向正确的方向,它还没有“完成”,但它给了我足够的时间来处理我现在知道如何做的事情。谢谢你,菲利普。
/* not the final method, see Philips answer for tryLoadCompiledType which validates this works */
private void sourceToUnitTest(string source, callBack CB) {
    var pro = new CSharpCodeProvider();

    var DOMref = AppDomain.CurrentDomain.GetAssemblies()
            .Where(obj => !obj.IsDynamic) 
            .Select(obj => obj.Location)
            .ToArray();

    var Cparams = new CompilerParameters( DOMref );
        Cparams.OutputAssembly = "SOURCE.DLL";

        CompilerResults res = pro.CompileAssemblyFromSource(Cparams, source);

        Assembly asm = res.CompiledAssembly;

        Type[] allTypes =  res.CompiledAssembly.GetTypes();

        foreach (Type t in allTypes)
        {
            TryLoadCompiledType(res, t.ToString());
            Debug.WriteLine(t.ToString());
        }


        /* I don't return I do something with each type here */
}
public CompilerResults CompileSource(string sourceCode)
{
        var csc = new CSharpCodeProvider(
            new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } });

        var referencedAssemblies =
                AppDomain.CurrentDomain.GetAssemblies()
                .Where(a => !a.FullName.StartsWith("mscorlib", StringComparison.InvariantCultureIgnoreCase))
                .Where(a => !a.IsDynamic) //necessary because a dynamic assembly will throw and exception when calling a.Location
                .Select(a => a.Location)
                .ToArray();

        var parameters = new CompilerParameters(
            referencedAssemblies);

        return csc.CompileAssemblyFromSource(parameters,
            sourceCode);
 }
 public static object TryLoadCompiledType(this CompilerResults compilerResults, string typeName, params object[] constructorArgs)
    {
        if (compilerResults.Errors.HasErrors)
        {
            Log.Warn("Can not TryLoadCompiledType because CompilerResults.HasErrors");
            return null;
        }

        var type = compilerResults.CompiledAssembly.GetType(typeName);

        if (null == type)
        {
            Log.Warn("Compiled Assembly does not contain a type [" + typeName + "]");
            return null;
        }

        return Activator.CreateInstance(type, constructorArgs);
    }
   public void Example(){
       dynamic instance = 
            CompileSource("namespace Test{public class DynamicCompile{ /*method*/}}")
            .TryLoadCompiledType("Test.DynamicCompile");

        //can now call methods on 'instance'
   }