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