При использовании CSharpCodeProvider.CompileAssemblyFromSource как ссылаться на интерфейс в работающем проекте? - PullRequest
0 голосов
/ 30 апреля 2019

У меня есть некоторый код, который работает и генерирует реализацию интерфейса во время выполнения.Я пытаюсь использовать CSharpCodeProvider, но когда я пытаюсь скомпилировать код с классом, реализующим интерфейс в том же коде, из запущенного приложения (которое выполняется в режиме отладки в Visual Studio), оно выдает исключение:

"Не удалось найти имя типа или пространства имен 'TestCodeGen' (отсутствует директива using или ссылка на сборку?)"

Мой код:

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

Как добавить ссылку на мой интерфейс и его пространство имен?Есть ли способ использовать parameters.ReferencedAssemblies.Add("WHAT_GOES_HERE?");?

1 Ответ

0 голосов
/ 01 мая 2019

Необходимо добавить ссылку на сборку, которая содержит IInterface. Вы можете использовать typeof(IInterface).Assembly.Location.

Чтобы создать экземпляр MyImpl, сначала необходимо получить тип с помощью 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();

}
...