如何在不重新编译的情况下从 CSharpCodeProvider 访问已编译的程序集



我有Microsoft.CSharp.CSharpCodeProvider CompileAssemblyFromSource工作。它绝对创造并返回我需要的东西。

我知道编译的代码最终会进入程序集,并且在处理应用程序域之前无法删除。

如何重用编译的调用,而不必每次都调用 CompileAssemblyFromSource(myParams, myScript)?

如果我设置 myParams.OutputAssembly = 'MyAssembly";我似乎无法实例化它的实例。

如果代码在内存中,我如何检查它是否存在以及如何在不调用 CompileAssemblyFromSource() 的情况下重新加载它?

找到了一个可能的解决方案。至少在我的测试应用程序中工作。不使用"输出程序集"设置时,.NET 将使用随机名称创建程序集。

我从返回的代码对象中获取了名称。objectReturn.GetType().模块.范围名称。

保存该名称,因此当我回来时,如果脚本没有更改,我可以只使用上次编译的版本。

请记住,每次编译时,它都会在程序集中创建一个新条目。这可以在AppDomain.CurrentDomain.GetAssemblies()中看到。

/// <summary>
/// 
/// </summary>
/// <param name="scriptString">My string i want to compile</param>
/// <param name="lastCompiledName">The random name .NET gave to my last in MEMORY compile
/// objectReturned.GetType().Module.ScopeName.Replace(".dll", "") to get the name.</param>
/// <param name="doForceCompile">If i want to override the one in MEMORY</param>
/// <param name="errors"></param>
/// <returns></returns>
public IScriptBuilder CompileCodeDomCSharp(String scriptString, string lastCompiledName, bool doForceCompile, out List<string> errors)
{
    var providerOptions = new Dictionary<string, string>();
    providerOptions.Add("CompilerVersion", "v4.0");
    var provider = new Microsoft.CSharp.CSharpCodeProvider(providerOptions);

    var cp = new CompilerParameters(new[] { "System.Core.dll" }) {
        GenerateExecutable = false,
        GenerateInMemory = true,
        TreatWarningsAsErrors = false,
        WarningLevel = 3,
        CompilerOptions = "/optimize",
        IncludeDebugInformation = false
    };
    cp.ReferencedAssemblies.Add(typeof(IScriptBuilder).Assembly.Location);
    // will write file to  C:newprojectsNewPayrollUtilitiesCSharpScriptingTestCSharpScriptWriterCSharpScriptWriterbinDebug  -- causes issues for me.
    // cp.OutputAssembly = "MyScriptRunner";        
    errors = new List<string>();
    try
    {
        var assemblies = AppDomain.CurrentDomain.GetAssemblies();
        Type type;
        // use actual name if OutputAssembly is set
        // if (doForceCompile || x.All(a => a.FullName != "MyScriptRunner, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"))   
        if (doForceCompile || assemblies.All(a => a.FullName != lastCompiledName + ", Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"))
        {
            var results = provider.CompileAssemblyFromSource(cp, scriptString);
            type = results.CompiledAssembly.GetType("MyScriptRunner");
        }
        else
        {
            // use actual name if OutputAssembly is set
            // var myScriptRunner = x.FirstOrDefault(a => a.FullName == "MyScriptRunner, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");   
            var myScriptRunner = assemblies.FirstOrDefault(a => a.FullName == lastCompiledName + ", Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
            var myScriptRunnerObject = myScriptRunner.CreateObject("*");
            type = myScriptRunnerObject.GetType();
        }

        dynamic obj = Activator.CreateInstance(type);
        return (IScriptBuilder)obj;
    }
    catch (Exception ex)
    {
        // Not returning or handling error an my test app.
        return null;
    }
}

相关内容

  • 没有找到相关文章

最新更新