-5

I'll try to define as mush as possible my problem and forget nothing.

For my project, which use a webRequest, I would like to compile dynamically my webRequest. For this I used the CodeDomProvider in a Private Assembly and a public MethodInfo who gives me back a " method" that I can use in my main program. So the main problem is that in my CompileCode, my MethodInfo method = type.getMethod(functionname); gives me a NullReferenceException error. I know it's because my type.getMethod(functionname) can't work on a type which is null. I tried to modify the fact that my object instance and Type type are not null, but I can't give them values because of their gender and I get stuck in the fact that they stay null and gives me no values...

I also saw that lot of people used Linq, but as I am compiling a whole .cs file, I can't write it all like this with the @"using System.Linq;";

So here are the partial code were the problem is :

Thank you

namespace testCodeCompiler
{
    public class CodeCompiler
    {
    public CodeCompiler()
    {
    }
    public MethodInfo CompileCode(string code, string namespacename, string classname,string functionname, bool isstatic, params object[] args)
    {
        Assembly asm = BuildAssembly(code);
        object instance = null;
        Type type = null;
        if (isstatic)
        {
            type = asm.GetType(namespacename + "." + classname);
        }
        else
        {
            instance = asm.CreateInstance(namespacename + "." + classname);
            type = instance.GetType();
        }
        MethodInfo method = type.GetMethod(functionname); // here is the error
        return method;
    }

    private Assembly BuildAssembly(string code)
    {
        CSharpCodeProvider provider = new CSharpCodeProvider();
        CompilerParameters compilerparams = new CompilerParameters();
        compilerparams.GenerateExecutable = false;
        compilerparams.GenerateInMemory = true;
        compilerparams.ReferencedAssemblies.Add("System.dll");
        compilerparams.ReferencedAssemblies.Add("System.Xml.dll");
        System.Reflection.Assembly currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
        compilerparams.ReferencedAssemblies.Add(currentAssembly.Location);
        CompilerResults results = provider.CompileAssemblyFromSource(compilerparams, code);
        if (results.Errors.HasErrors)
        {
            StringBuilder errors = new StringBuilder("Compiler Errors :\r\n");
            foreach (CompilerError error in results.Errors )
            {
                errors.AppendFormat("Line {0},{1}\t: {2}\n", error.Line, error.Column, error.ErrorText);
            }
            throw new Exception(errors.ToString());
        }
        else
        {
            return results.CompiledAssembly;
        }
    }
}

And a little part of the Main() :

static void Main(string[] args)
{
    MethodInfo method;
    [// Little bit of code ]
    StreamReader sr = new StreamReader(@"c:\pathtothefileIwant\File.cs", System.Text.Encoding.Default);
    string file = sr.ReadToEnd();
    sr.Close();
    CodeCompiler cc = new CodeCompiler();

    object[] arguments = { popup }; // here are the args which are in another class
    [...little bit of code...]

    method = cc.CompileCode(file, "testNamespace", "Class1", "webRequest", true, arguments);

     List<Test> li = (List<Test>)method.Invoke(null, arguments); // Here I invoke the method to put it in a List<Compte> I made before.
}
Servy
  • 202,030
  • 26
  • 332
  • 449
Anynahel
  • 41
  • 6
  • So your problem is that `asm.GetType(namespacename + "." + classname)` returns `null`, which means your generated assembly doesn't contain a type in that namespace, which is pretty logical because you don't use those variables in your compilation method. – CodeCaster Feb 12 '16 at 14:05
  • In that part of the code it's a mystery too because in `type = asm.GetType(namespacename + "." + classname)` the namespacename and classname gets their values which are (testNM and Class1) but they don't go in the type who still stay null after the `if (isstatic){}`. And `asm` have `{jd5mkjjd, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null}` in value. The first parameter is always random ( if it can give you help or any clues ) – Anynahel Feb 12 '16 at 14:15
  • Look, you're compiling `string code`, which apparently does not contain `namespace Your.Namespace.Name { public class YourClassName { } }`, so that `GetType()` returns `null`. – CodeCaster Feb 12 '16 at 14:16
  • I just verified and with the debug mode on Visual Studio I see that those strings are not empty because `method = cc.CompileCode(file, "testNamespace", "Class1", "webRequest", true, arguments);` in the Main() Program get in the `public MethodInfo CompileCode{}` and give the parameters I wrote. – Anynahel Feb 12 '16 at 14:27
  • I am not saying those strings are empty. I'm saying that the code you're trying to compile at runtime does not contain the namespace and class name that you're looking for in your `GetType()` call. The `string namespacename` and `string classname` must point to an actual type in an actual namespace that's in the `code` string. – CodeCaster Feb 12 '16 at 14:29
  • 1
    Thank you, you were right, the problem was in the fact that it was not the right classname in the `code string` so instead of `method = cc.CompileCode(file, "testNamespace", "Class1", "webRequest", true, arguments);` I put `method = cc.CompileCode(file, "testNamespace", "RequeteWeb", "webRequestl", true, arguments);` I didn't saw that. The exception is now gone. I have another one, but this one is easier to correct. Thank you again. – Anynahel Feb 12 '16 at 14:41
  • If you've found a solution to your problem then post it as an answer, not as an edit to the question. – Servy Feb 12 '16 at 14:55

1 Answers1

0

The problem was in the class Program Main(){ method = cc.CompileCode(file, "testNamespace", "Class1", "webRequest", true, arguments);} The string classname was not the good one and didn't pointed to the real document I wanted to compile. The good path was method = cc.CompileCode(file,"testNamespace", "WebRequest","webRequest", true, arguments);} That's why the Type type; couldn't get something instead of null.

Anynahel
  • 41
  • 6