저는 C# 코드 줄을 받아들이고이를 주변 코드로 묶어서 어셈블리로 컴파일하는 콘솔 유형을 가지고 있습니다. 그런 다음 해당 어셈블리에서 메서드를 호출하고 결과를 출력하면됩니다.런타임 컴파일이 제거 할 수없는 파일을 생성합니다.
문제는 어셈블리에 이름이 있어야하므로 비공개 클래스에 액세스 할 수 있도록 친구 어셈블리로 설정할 수 있다는 것입니다. 나는 그것을 "콘솔"이라고 명명했다.
예상대로 작동하지만 "console"이라는 파일이 이미 디렉토리에 있고 덮어 쓸 수 없기 때문에 두 번째 스크립트를 실행할 수 없다는 문제가 있습니다.
나는 Dispose 메서드가있는 모든 것을 처리하려고 시도했습니다. File.Delete 수동으로 파일을 삭제하려고했습니다. 아무것도 도움이되지 않았습니다.
그래서 여기에 제가 사용하고있는 코드가 있습니다. 누군가가 나를 도울 수 있기를 바랍니다.
CSharpCodeProvider provider = new CSharpCodeProvider();
var param = new CompilerParameters();
param.GenerateInMemory = false;
param.GenerateExecutable = false;
param.OutputAssembly = "console";
param.ReferencedAssemblies.Add("System.dll");
param.ReferencedAssemblies.Add("System.Core.dll");
param.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
var results = provider.CompileAssemblyFromSource(param,
@"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace FireflyGL
{
class DebugConsole
{
static void Run(StringWriter writer)
{
var stdOut = Console.Out;
Console.SetOut(writer);
" + input.Text + @"
Console.SetOut(stdOut);
}
}
}");
if (results.Errors.HasErrors)
{
for (int i = 0; i < results.Errors.Count; ++i)
{
PushText(results.Errors[i].ErrorText);
}
}
else
{
try
{
var writter = new StringWriter();
results.CompiledAssembly.GetType("FireflyGL.DebugConsole").GetMethod("Run", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[] { writter });
PushText(writter.ToString());
history.Add(input.Text);
currentHistory = history.Count;
input.Text = "";
writter.Dispose();
}
catch (Exception)
{
}
}
provider.Dispose();
File.Delete(results.CompiledAssembly.Location);
나는 온라인 예를 참조했다 그러나 나는 어떻게 정말로 이해하지 못한다. 어셈블리를 특정 AppDomain에서 참조하도록하려면 어떻게합니까? –
신경 쓰지 마십시오. 내가 대답을 찾았 : http://stackoverflow.com/questions/1799373/how-can-i-prevent-compileassemblyfromsource-from-leaking-memory –
그것에 대해 갈 다른 방법이 있습니까? 나는 놀고 있었고 AppDomain은 나에게 많은 문제를주고있다. 스크립트에 객체 참조를 보낼 수 있어야하지만 이상한 "객체가 직렬화되지 않음"예외가 발생합니다. –