如何避免在C#中多次加载程序集?

时间:2014-11-06 09:06:24

标签: c# .net-assembly expression-evaluation

我在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;

0 个答案:

没有答案