0

I have some code that is running and generates an implementation of an interface at runtime. I am trying to use CSharpCodeProvider but when I try to compile code that has a class implementing an interface in the same code from the running application (which is running in debug mode in Visual Studio), it throws an exception:

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

My code:

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Web.Http;
using Microsoft.CodeDom.Providers.DotNetCompilerPlatform;

namespace TestCodeGen
{
    public class TestApp
    {
        public static void Main(string[] args)
        {
            CSharpCodeProvider provider = new CSharpCodeProvider();

            CompilerParameters parameters = new CompilerParameters();
            parameters.GenerateExecutable = false;
            parameters.GenerateInMemory = true;
            parameters.OutputAssembly = "MyImpl";

            CompilerResults results = provider.CompileAssemblyFromSource(
                parameters,
                @"
                    using TestCodeGen;
                    public class MyImpl : IInterface
                    {
                        public string GetName()
                        {
                            return ""test"";
                        }
                    }
                "
            );

            IInterface impl = (IInterface) Activator.CreateInstance(null, "MyImpl");


        System.Diagnostics.Debug.WriteLine(impl.GetName());
        }
    }

    public interface IInterface
    {
        string GetName();
    }
}

How would I add a reference to my interface and its namespace? Is there some way to use parameters.ReferencedAssemblies.Add("WHAT_GOES_HERE?");?

5
  • Probably something like Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.8.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 You should look for the exact name/version Commented Apr 30, 2019 at 18:20
  • @J.vanLangen I think this might work (looking into it): parameters.ReferencedAssemblies.Add(typeof(TestApp).Assembly.Location); Commented Apr 30, 2019 at 18:25
  • or parameters.ReferencedAssemblies.Add(typeof(TestApp).Assembly.FullName); Commented Apr 30, 2019 at 18:28
  • @J.vanLangen What's the difference between these two? Why is full name better? Commented Apr 30, 2019 at 18:51
  • Some assemblies should be loaded from the GAC, so a fullname which includes a version, will fix this aswell. Commented May 1, 2019 at 7:49

1 Answer 1

1

You need to add a reference to the assembly that contains IInterface. You can use typeof(IInterface).Assembly.Location.

To create an instance of MyImpl, you first need to get the type using results.CompiledAssembly.GetType("MyImpl")

using System;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

public class TestApp
{
    public static void Main(string[] args)
    {
        CSharpCodeProvider provider = new CSharpCodeProvider();

        CompilerParameters parameters = new CompilerParameters();
        parameters.GenerateExecutable = false;
        parameters.GenerateInMemory = true;
        parameters.OutputAssembly = "MyImpl";
        parameters.ReferencedAssemblies.Add(typeof(IInterface).Assembly.Location);

        CompilerResults results = provider.CompileAssemblyFromSource(
            parameters,
            @"
                    public class MyImpl : IInterface
                    {
                        public string GetName()
                        {
                            return ""test"";
                        }
                    }
                "
        );

        var myImplType = results.CompiledAssembly.GetType("MyImpl");
        IInterface impl = (IInterface)Activator.CreateInstance(myImplType);


        System.Diagnostics.Debug.WriteLine(impl.GetName());
    }
}

public interface IInterface
{
    string GetName();

}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.