Как создать новый тип в C # - PullRequest
0 голосов
/ 04 мая 2011

Я действительно хочу создать новый тип во время выполнения. По сути, я хочу создать типы, которые выглядят примерно так:

public class MySpecial123
{
    public Func<int, DateTime, int> salesVectorCalc; // field

    public int CallSalesVectorCalculation(int i, DateTime d)
    (
        return salesVectorCalc(i, d);
    )
}

Некоторые типы будут различаться в зависимости от ввода данных пользователем / БД, поэтому я не могу сделать это иначе, чем создать тип во время выполнения. Это также более сложная задача, но я хотел упростить свой вопрос, поэтому здесь я задаю только основные вопросы. Мне нужно будет сделать больше поколений, чем то, что вы видите здесь.

Я думал, что было бы здорово использовать Reflection.Emit, но потом я понял, что может быть проще сгенерировать код и скомпилировать все в памяти. Кто-нибудь знает, что лучше? Мне бы очень хотелось увидеть пример того, как это сделать.

Ответы [ 2 ]

5 голосов
/ 04 мая 2011

Когда вы говорите «генерировать тип во время выполнения», это звучит так, как будто вы запрашиваете динамическая типизация .

В C # 4.0 это делается просто с ключевым словом dynamic.

Однако вы также описываете что-то похожее на генерацию кода - если это больше, чем вы хотите, почему бы не использовать что-то вроде шаблонов T4 для генерации ваших типов в фазе «предварительной компиляции»?

2 голосов
/ 04 мая 2011

Довольно просто сгенерировать ваш код в виде строки, а затем динамически скомпилировать его в сборку в памяти.Затем вы можете вызвать ваши методы и получить доступ к вашим полям:

  • Использование отражения
  • Использование ключевого слова dynamic
  • Приведение к интерфейсу/ базовый класс (если ваш новый класс наследует от одного)

Код:

public static Assembly Compile(string source)
{
    var codeProvider = new CSharpCodeProvider(new Dictionary<String, String> { { "CompilerVersion", "v4.0" } });
    var compilerParameters = new CompilerParameters();

    compilerParameters.ReferencedAssemblies.Add("System.dll");
    compilerParameters.ReferencedAssemblies.Add("System.Core.dll");
    compilerParameters.ReferencedAssemblies.Add("System.Xml.dll");
    compilerParameters.ReferencedAssemblies.Add("System.Xml.Linq.dll");
    compilerParameters.CompilerOptions = "/t:library";
    compilerParameters.GenerateInMemory = true;

    var result = codeProvider.CompileAssemblyFromSource(compilerParameters, source);
    if (result.Errors.Count > 0)
    {
        foreach (CompilerError error in result.Errors)
        {
            Debug.WriteLine("ERROR Line {0:000}: {1}", error.Line, error.ErrorText);
        }
        return null;
    }
    else
    {
        return result.CompiledAssembly;
    }
}
...