所以,在对如何沙箱ac#script编译器进行大量研究以使加载的程序集只加载到沙箱AppDomain而不是我的主AppDomain之后,我遇到了所有dll的问题所在在卸载沙箱AppDomain EXCEPT FOR ONE时卸载已创建。那个是来自一个看起来像的脚本:
return new Func<List<int>,int>
(
(list) =>
{
var total = 0;
foreach (int i in list)
{
total += i;
}
return total;
}
);
现在,脚本返回的结果是它们最终都会在字典中返回到主AppDomain。其余的脚本都返回简单的可序列化对象或基元,正如我所说的所有程序集正确卸载,我能够删除主域仍处于活动状态。这个特定的返回是否有可能将创建程序集“传递”回主AppDomain,因为它的值是Func?有没有办法解决这个问题?
我首先拥有沙箱的原因是,在运行一组脚本之后,我可以处理执行它们的对象,并且dispose方法卸载沙箱域并删除所有创建的程序集。我希望能够在一个持续运行的环境中使用它,比如一个Web服务器,其中程序集的构建是有问题的,并且目前,每次脚本集运行时返回一个Func,我将有一个挥之不去的程序集。我宁愿在使用这个库的文档旁边没有星号,所以欢迎任何想法。
作为参考,这是我编译脚本的代码:
var provider = new CSharpCodeProvider(new Dictionary<string, string>() { { CompilerOptionName, CompilerOptionVersion } });
var compilerParams = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = false };
compilerParams.ReferencedAssemblies.AddRange(References);
compilerParams.TempFiles = new TempFileCollection(BinPath);
compilerParams.OutputAssembly = Path.Combine(BinPath,
Utilities.AssemblyPrefix + ProfigurationExe.Profiguration.ID + "_" + Action.ID + "_Script" + Utilities.DllExt);
// If no object is returned by user code, enter in a return null to satisfy returning an object for
// default code template. If they do have a return that will return first.
Code = Code + ReturnNull;
var parameterString = BuildParameterString();
parameterString = !String.IsNullOrEmpty(parameterString) ? ", " + parameterString : String.Empty;
// If someone simply imports namespaces separated by spaces, commas, or semicolons, create a proper using statement
if (!String.IsNullOrEmpty(Imports) && !IsUsingRegex.IsMatch(Imports))
{
Imports = String.Join("; ", Imports.Split(" ,;".ToCharArray()).Select(s => Using + " " + s)) + "; ";
}
FinalCode = String.Format(Imports + CodeTemplate,
new object[] {DefaultNamespace, ClassName, DefaultMethod, parameterString, Code});
// This just is a variable of the code that will be compiled, with all spaces and line breaks removed
var debugFriendlierFinalCode = U.CompressWhiteSpaceRegex.Replace(FinalCode.Replace("\r", String.Empty).Replace("\n", String.Empty), U.OneSpace);
// Note that we are adding the import fields to the beginning in case user wants to import namespaces (and not have to always use fully qualified class names)
var results = provider.CompileAssemblyFromSource(compilerParams, FinalCode);
Assembly = results.CompiledAssembly;
if (!results.Errors.HasErrors)
{
return Assembly;
}
// If there were compiler errors, aggregrate them into an exception.
var errors = new StringBuilder("Dynamic Code Compiler Errors :\r\n");
foreach (CompilerError error in results.Errors)
{
errors.AppendFormat("Line {0},{1}\t: {2}\n",
error.Line, error.Column, error.ErrorText);
}
throw new ProfigurationException(errors.ToString());
答案 0 :(得分:4)
Func
是可序列化的,并且正在按照您的意图进行复制。但它指向驻留在要卸载的程序集内部的代码。这就是为什么程序集也在父AppDomain中加载。
不确定要推荐什么。我希望您无法卸载正在使用的代码。