动态编译代码中缺少程序集引用

9
感谢大家对我上一篇关于这个问题的帖子的留言。我将重新发布并尝试更加清晰地表述。我想这可能是一个微不足道的问题,但我真的卡住了,需要一些帮助。这是我第一次在这里发帖。
using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;
namespace DynamicCode
{
public class DynaCore
{
string WorkingCode = 
    "using System;"+
    "using System.Collections.Generic;"+
    "namespace DynaCore"+
    "{"+
    "   public class DynaCore"+
    "   {"+
    "       static public string DynamicResult()"+
    "       {"+
    "           return \"I'm compiled\";"+
    "       }"+
    "   }"+
    "}";


string PredicateTemplCode = 
    "using System;"+
    "using System.Linq;"+
    "using System.Collections.Generic;"+
    "namespace DynaCore"+
    "{"+
    "   public class DynaCore"+
    "   {"+
    "       static public Func<{1}, bool> DynamicResult()"+
    "       {"+
    "           return new Func<{1}, bool>({2});"+
    "       }"+
    "   }"+
    "}";

public DynaCore()
{
    string compiledString = WorkingCompilation(WorkingCode);
    Func<bool, bool> compiladePredicate = NotWorkingCompilation<bool>(PredicateTemplCode, "(o)=> true");
}

string WorkingCompilation(string code)
{
    var cParams = new CompilerParameters();
    cParams.GenerateInMemory = true;
    cParams.TreatWarningsAsErrors = false;
    cParams.GenerateExecutable = false;
    cParams.CompilerOptions = "/optimize /target:library";

    var curAss = Assembly.GetExecutingAssembly();

    cParams.ReferencedAssemblies.Add("System.dll");
    cParams.ReferencedAssemblies.Add("mscorlib.dll");
    cParams.ReferencedAssemblies.Add("System.dll");
    cParams.ReferencedAssemblies.Add("System.Data.dll");
    cParams.ReferencedAssemblies.Add(curAss.Location);

    var provider = new CSharpCodeProvider();

    var compalerResult = provider.CompileAssemblyFromSource(cParams, code);

    if (compalerResult.Errors.HasErrors)
    {
        var complieError = "";
        foreach (CompilerError ce in compalerResult.Errors)
            complieError += ce + " ";

        throw new Exception(complieError.Trim());
    }

    Module module = compalerResult.CompiledAssembly.GetModules()[0];
    Type mt = null;
    MethodInfo methInfo = null;

    return (string)module.GetType("DynaCore.DynaCore").GetMethod("DynamicResult").Invoke(null, null);
}


Func<T, bool> NotWorkingCompilation<T>(string code, string predicateString)
{
    var cParams = new CompilerParameters();
    cParams.GenerateInMemory = true;
    cParams.TreatWarningsAsErrors = false;
    cParams.GenerateExecutable = false;
    cParams.CompilerOptions = "/optimize /target:library";

    var curAss = Assembly.GetExecutingAssembly();

    cParams.ReferencedAssemblies.Add("System.dll");
    cParams.ReferencedAssemblies.Add("mscorlib.dll");
    cParams.ReferencedAssemblies.Add("System.dll");
    cParams.ReferencedAssemblies.Add("System.Data.dll");
    cParams.ReferencedAssemblies.Add("System.Core.dll");
    cParams.ReferencedAssemblies.Add(curAss.Location);

    var provider = new CSharpCodeProvider();

    var codeToRun = code.Replace("{1}", typeof(T).Name).Replace("{2}", predicateString);
    var compalerResult = provider.CompileAssemblyFromSource(cParams, codeToRun);

    if (compalerResult.Errors.HasErrors)
    {
        var complieError = "";
        foreach (CompilerError ce in compalerResult.Errors)
            complieError += ce + " ";

        throw new Exception(complieError.Trim());
    }

    Module module = compalerResult.CompiledAssembly.GetModules()[0];
    Type mt = null;
    MethodInfo methInfo = null;

    return (Func<T, bool>)module.GetType("DynaCore.DynaCore").GetMethod("DynamicResult").Invoke(null, null);
}
}
}

问题在于,当我在 ReferencedAssemblies.Add("System.Core.dll") 中引用 System.Core.dll 时,它会给我一个编译器错误:

error CS0006: 找不到元数据文件 'System.Core.dll'

我正在使用 v3.5 和 VS 2008。

5个回答

10

感谢所有回答!

原来CSharpCodeProvider默认使用不支持泛型或linq的2.0版本。以下内容解决了问题:

var provider = new CSharpCodeProvider(
    new Dictionary<String, String>{{ "CompilerVersion","v3.5" }});

这甚至不是有效的C#代码。真正的解决方案是什么? - James Dunne
3
啊,Dictionary 后面缺少 <string, string>。我猜 Stack Overflow 把它当做标记语言给移除了? - James Dunne

6

我想更新这个帖子,因为它从未得到正确的回答。我刚刚遇到了同样的问题(CS0006),需要包含一个在WPF目录中的WPF库,并最终通过以下方式解决:

            string ver = string.Format("{0}.{1}.{2}", Environment.Version.Major, Environment.Version.MajorRevision, Environment.Version.Build);
            string exWpfDir = string.Format(@"C:\WINDOWS\Microsoft.NET\Framework\v{0}\WPF", ver);
            string exDir = string.Format(@"C:\WINDOWS\Microsoft.NET\Framework\v{0}", ver);

            CSharpCodeProvider provider = new CSharpCodeProvider();
            ICodeCompiler compiler = provider.CreateCompiler();
            CompilerParameters compilerparams = new CompilerParameters();
            compilerparams.GenerateExecutable = false;
            compilerparams.GenerateInMemory = true;
            compilerparams.IncludeDebugInformation = false;
            compilerparams.TreatWarningsAsErrors = false;
            compilerparams.CompilerOptions = string.Format("/lib:{0}", exWpfDir);
            compilerparams.CompilerOptions = string.Format("/lib:{0}", exDir);

1
你是不是想在最后一行覆盖 CompilerOptions? - Triynko
抱歉,那个有点粗糙。我只是在测试这两个,没有注释掉之前的代码。感谢你指出来。 - Rob

2

另一个问题可能是System.Core.dll实际上位于与其他提到的dll不同的位置。

在我的电脑上,System.Core.dll位于%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll,而其他dll位于GAC中。


1
是的,但全局程序集缓存与此无关。位于与C#编译器csc.exe相同文件夹中的程序集可以在不指定完整路径的情况下被找到。c:\windows\microsoft.net\framework\v2.0.50727 - Hans Passant
我的 System.Core.dll 与你的位于同一目录下,但如果我使用 "ReferencedAssemblies.Add(@"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll");" 仍然会出现错误。 - Saul Goodman

1
有时候你需要将所需引用的程序集添加到CSharpCodeProvider参数中。
parameters.ReferencedAssemblies.Add("System.dll");

希望这有所帮助。

0

生成的代码

using System;
using System.Linq;
using System.Collections.Generic;
namespace DynaCore
{
    public class DynaCore
    {
        static public Func<Boolean, bool> Main()
        {
            Func<Boolean, bool> retur = (o) => true;
        }
    }
}

当粘贴到新文件中时,代码本身不会编译。第一个编译错误是

'DynaCore.DynaCore.Main()': not all code paths return a value

首先,您需要生成在空的 .cs 文件中粘贴后可以编译的代码。

第一件明显的事情是将 func 语句修复为类似以下内容的语句:

return new Func<Boolean, bool>(o => true);

编辑:
不要调用方法Main


谢谢回复,但即使这些问题得到解决,我仍然会收到相同的错误 :/ - Saul Goodman
奇怪,我不知道,但我正在运行vs2010。 - Albin Sunnanbo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接