1

I want to return a custom class (ex. User) from a function which created by a Codedom. My Userclass in another class library in the same solution with my Windows Application which I use it for Dynamic Code generation.

CompilerResult returns these errors:

The type or namespace name 'TestApp' could not be found (are you missing a using directive or an assembly reference?)

The type or namespace name 'User' could not be found (are you missing a using directive or an assembly reference?)

Here is my code :

StringBuilder sbCode = new StringBuilder();

sbCode.Append(@"using System.Windows.Forms;");
sbCode.Append(@"using Nikola.BusinessIntelligence.Objects;");
sbCode.Append(@"using System.Collections.Generic;");
sbCode.Append(@"using System.Text;");
sbCode.Append(@"using Microsoft.CSharp;");
sbCode.Append(@"using TestApp.Data;"); // User class is in this Class Lib

sbCode.Append(" public class Test {");
sbCode.Append(tbCode.Text);
sbCode.Append("}");

var cp = new CompilerParameters()
{
    GenerateInMemory = true,
    GenerateExecutable = false,
    ReferencedAssemblies =
    {
        "System.dll",
        "System.Core.dll",
        "System.Windows.dll",
        "System.Windows.Forms.dll",
    },
};

using (CSharpCodeProvider codeProvider = new CSharpCodeProvider())
{
    CompilerResults res = codeProvider.CompileAssemblyFromSource(cp, sbCode.ToString());
    var type = res.CompiledAssembly.GetType("Test");
    var obj = Activator.CreateInstance(type);
    var output = type.GetMethod("Execute").Invoke(obj, new object[] { });
}

And here is my sample code which I write in tbCode text box:

public User  Execute()
        {
            User usr = new User();
            return usr;
        }
mkj
  • 2,761
  • 5
  • 24
  • 28
cagin
  • 5,772
  • 14
  • 74
  • 130

2 Answers2

1

Two problems:

  1. You forgot namespace:

    sbCode.Append(" namespace SomeNameSpace{public class Test {");
    sbCode.Append(tbCode.Text);
    sbCode.Append("}}");
    
  2. There is missing = in code you are trying:

    User usr = new User();
    

In regards of compiler errors, you have to add missing assemblies. Try to add all used by current assembly like this:

var options = new CompilerParameters();
// add all loaded assemblies
options.ReferencedAssemblies.AddRange(
    AppDomain.CurrentDomain.GetAssemblies().Where(item => !item.IsDynamic).Select(item => item.Location).ToArray());
options.GenerateExecutable = false;
options.GenerateInMemory = true;

// compile like this
var result = provider.CompileAssemblyFromSource(options, source);
if (result.Errors.HasErrors)
{
    // deal with errors
}
Sinatr
  • 20,892
  • 15
  • 90
  • 319
  • I add the napespace as you told and now only The type or namespace name 'User' could not be found (are you missing a using directive or an assembly reference?) error I have. – cagin Jan 12 '16 at 09:05
1

Obviously if you type a using something; in your code, you must add the something related referenced assembly in the list of referenced assemblies used in CompilerParameters :

var cp = new CompilerParameters()
        {
            GenerateInMemory = true,
            GenerateExecutable = false,
            ReferencedAssemblies =
            {
                "System.dll",
                "System.Core.dll",
                "System.Windows.dll",
                "System.Windows.Forms.dll",
                // I assume the following name of the assembly
                // however you should update it to the relevant name if needed
                "TestApp.Data.dll"
                },

        };
Fab
  • 14,327
  • 5
  • 49
  • 68
  • My CompilerResults does not have any error right now but this time res.CompiledAssembly.GetType("Test"); returns null. Do you have any suggestion about it? – cagin Jan 12 '16 at 09:17
  • Did you debug and check if the class string (sbCode) formed is in a correct format? – Joe 89 Jan 12 '16 at 09:20
  • @MohanPrasath, Yes I checked it. It is in correct format – cagin Jan 12 '16 at 09:24
  • @cagin it's because you've added a namespace. It's not needed. I've checked the code on my machine and that should work. Check the visibility of Test and User (it should be public). Either remove namespace or use `var type = res.CompiledAssembly.GetType("SomeNameSpace.Test");` – Fab Jan 12 '16 at 09:26
  • I am surprised `namespace` is indeed optional, but this has [consequences](http://stackoverflow.com/q/15463449/1997232) (putting everything in `global` feels wrong). – Sinatr Jan 12 '16 at 10:16