C # - ссылка на тип в динамически сгенерированной сборке - PullRequest
16 голосов
/ 14 мая 2010

Я пытаюсь выяснить, возможно ли при динамическом создании сборок ссылаться на тип в ранее динамически создаваемой сборке.

Например:

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

CodeDomProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();

parameters.GenerateInMemory = true;

CompilerResults results = provider.CompileAssemblyFromSource(parameters, @"
namespace Dynamic
{
    public class A
    {
    }
}
");

Assembly assem = results.CompiledAssembly;

CodeDomProvider provider2 = new CSharpCodeProvider();
CompilerParameters parameters2 = new CompilerParameters();

parameters2.ReferencedAssemblies.Add(assem.FullName);
parameters2.GenerateInMemory = true;

CompilerResults results2 = provider2.CompileAssemblyFromSource(parameters2, @"
namespace Dynamic
{
    public class B : A
    {
    }
}
");

if (results2.Errors.HasErrors)
{
    foreach (CompilerError error in results2.Errors)
    {
        Console.WriteLine(error.ErrorText);
    }
}
else
{
    Assembly assem2 = results2.CompiledAssembly;
}

Этот код печатает на консоли следующее: The type or namespace name 'A' could not be found (are you missing a using directive or an assembly reference?)

Я пробовал много разных способов, но, похоже, ничего не работает. Я что-то пропустил? Это вообще возможно?

РЕДАКТИРОВАТЬ: Исправление ошибки в коде обеспечивает вместо этого эту ошибку: Metadata file 'l0livsmn, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' could not be found

EDIT2: примечание, но если изменить GenerateInMemory на false и выполнить parameters2.ReferencedAssemblies.Add(assem.Location);, это приведет к правильной компиляции, но я бы предпочел ссылаться на сборку, которая находится непосредственно в памяти, а не выводить временные файлы.

Ответы [ 2 ]

4 голосов
/ 14 мая 2010

Я думаю, что в

CompilerResults results2 = provider2.CompileAssemblyFromSource(parameters, @"
namespace Dynamic
{
    public class B : A
    {
    }
}
");

Вы хотите передать parameters2, а не parameters.

Я нашел способ сделать это, вам НЕ нужно компилировать первый в памяти, если вы этого не сделаете, он создаст dll для этой сборки в вашем временном каталоге, плюс в вашем вызове

ReferencedAssemblies.Add() 

вы не передаете имя сборки, вы передаете путь сборки, посмотрите на этот код, он должен работать без нареканий:

        CodeDomProvider provider = new CSharpCodeProvider();
        CompilerParameters parameters = new CompilerParameters();            

        CompilerResults results = provider.CompileAssemblyFromSource(parameters, @"
            namespace Dynamic
            {
                public class A
                {
                }
            }
            ");

        Assembly assem = results.CompiledAssembly;

        CodeDomProvider provider2 = new CSharpCodeProvider();
        CompilerParameters parameters2 = new CompilerParameters();

        parameters2.ReferencedAssemblies.Add(assem.Location);
        parameters2.GenerateInMemory = true;

        CompilerResults results2 = provider2.CompileAssemblyFromSource(parameters2, @"
            namespace Dynamic
            {
                public class B : A
                {
                }
            }
            ");

        if (results2.Errors.HasErrors)
        {
            foreach (CompilerError error in results2.Errors)
            {
                Console.WriteLine(error.ErrorText);
            }
        }
        else
        {
            Assembly assem2 = results2.CompiledAssembly;
        }
2 голосов
/ 14 мая 2010

MSDN говорит, что вы можете:

Ограничения на типовые ссылки

Сборки могут ссылаться на определенные типы в другой сборке. переходный процесс динамическая сборка может смело ссылаться типы, определенные в другом переходном процессе динамическая сборка, постоянный динамическая сборка или статическая сборка. Однако общее язык выполнения не позволяет постоянный динамический модуль для ссылаться на тип, определенный в переходный динамический модуль. Это потому что, когда сохраняющийся динамический модуль загружается после сохранения в диск, среда выполнения не может разрешить ссылки на типы, определенные в переходный динамический модуль.

...