我在C#中有一个表达式求值程序项目,它生成IL并将IL转换为评估方法。问题在于,无法从C#卸载程序集,并且每次调用表达式求值时,编译器都会继续将程序集添加到当前应用程序上下文中。我可以做的一件事就是创建一个appdomain,在appdomain中生成IL,并在生成IL之后终止appdomain。
以下是执行此操作的示例代码。有人能告诉我处理多装配加载问题的有效方法吗?
DynamicMethodState methodState;
// Use CodeDom to compile using C#
CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters loParameters = new CompilerParameters();
// Add assemblies
loParameters.ReferencedAssemblies.Add("System.dll");
loParameters.ReferencedAssemblies.Add(functionType.Assembly.Location);
// Don't generate assembly on disk and treat warnings as errors
loParameters.GenerateInMemory = true;
loParameters.TreatWarningsAsErrors = true;
// Set name space of the dynamic class.
string dynamicNamespace = "ExpressionEval.Functions.Dynamic";
string source = @"
using System;
using {5};
namespace {6}
{{
public class {0} : {1}
{{
public {2} {3}()
{{
return {4};
}}
}}
}}
";
// Set source code replacements
string className = "Class_" + Guid.NewGuid().ToString("N");
string methodName = "Method_" + Guid.NewGuid().ToString("N");
string returnTypeName = returnType.FullName;
// Check for generic type for return
if (returnType.IsGenericType)
{
// Check for null-able
Type genericType = returnType.GetGenericTypeDefinition();
if (genericType == typeof(Nullable<>))
{
// Nullable so add ?
Type nullableType = Nullable.GetUnderlyingType(returnType);
returnTypeName = nullableType.FullName + "?";
}
else
{
// Not nullable but is generic so get the list of types
Type[] genericArgTypes = returnType.GetGenericArguments();
// Get type name without the last 2 characters for generic type names
returnTypeName = genericType.FullName.Substring(0, genericType.FullName.Length - 2) + "<";
// Loop through type arguments and build out return type
foreach (Type genericArgType in genericArgTypes)
{
returnTypeName += genericArgType.FullName;
}
// Add ending generic operator
returnTypeName += ">";
}
}
// Format code string with replacements.
string codeString = string.Format(CultureInfo.InvariantCulture, source, className, functionType.FullName, returnTypeName, methodName, expression, functionType.Namespace, dynamicNamespace);
// Compile the code.
CompilerResults results = codeProvider.CompileAssemblyFromSource(loParameters, codeString);
if (results.Errors.Count > 0)
{
// Throw an exception for any errors.
throw new ApplicationException("Compile of policy failed.");
}
else
{
// Get the type that was compiled.
Type dynamicType = results.CompiledAssembly.GetType(dynamicNamespace + "." + className);
// Get the MethodInfo for the compiled expression.
MethodInfo dynamicMethod = dynamicType.GetMethod(methodName);
// Get the compiled expression as serializable object.
methodState = GetMethodState(dynamicMethod);
}
return methodState;