开发者

Missing assembly references in dynamically compiled code

Thanks for the messages about my first post about this problem. I will do a repost and try to be more clear this time. I guess this may be a trivial problem but I'm really stuck and need some help. This is my first time posting here.

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 Excepti开发者_运维百科on(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);
}
}
}

The problem is that when I reference System.Core.dll in ReferencedAssemblies.Add("System.Core.dll"), it gives me a compiler error:

error CS0006: Metadata file 'System.Core.dll' could not be found

I'm using v3.5 and VS 2008.


Thanks for all the answers!

It turns out that CSharpCodeProvider defaults to version 2.0 that have no support for generics or linq. The following fixed the problem:

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


I thought I'd update this thread since it was never properly answered. I just came across the same issue (CS0006), having to include a WPF library that was in the WPF directory, and wound up fixing it with the following:

            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);


Another issue may be that System.Core.dll is actually in a different location than the other dlls mentioned.

On my machine, System.Core.dll is located in %ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll, whereas the other dlls are in the GAC.


Sometimes you need to add the referenced assembly to the CSharpCodeProvider parameters.

parameters.ReferencedAssemblies.Add("System.dll");

Hope this helps.


The resulting code

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;
        }
    }
}

does not compile itself when pasted into a new file. First compilation error is

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

First you need to generate code thats compiling when pasted into a empty .cs file.

The first obvious thing is to fix the func-statement into something like

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

Edit:
And don't call the method Main.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜