Как можно ввести литеральное выражение, используя Reflection.Emit?

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

У меня есть рабочая модель, использующая CodeDOM и рефлексию, чтобы сгенерировать класс оценщика, создать и загрузить сборку (GenerateInMemory = true), создать экземпляр класса и выполнить метод оценки. Тем не менее, я хочу загрузить сборку в AppDomain, чтобы я мог выгрузить ее после завершения выполнения. При исследовании этой проблемы я был направлен на метод AppDomain.DefineDynamicAssembly. Похоже, это именно то, что мне нужно, поскольку я могу создать коллекционную сборку.

Вот пара примеров пользовательских выражений и классов, сгенерированных моим проектом CodeDOM:

Простое пользовательское выражение :

return Abs(@HDL@/@LDL@ * 5.5);

Сгенерированный класс:

namespace Lab.ResultProcessing
{

    public sealed class ExpressionEvaluator
    {
        public double Evaluate()
        {
            return System.Math.Abs(449.86881550861/74.934407754305 * 5.5);
        }
    }
}

Более сложное пользовательское выражение:

double GFR;
double MA_GFR;
double MB_GFR;
double FA_GFR;
double FB_GFR;

GFR = (170 *
        Pow(@CREAT@, -0.999) *
        Pow(@YEARS@, -0.176) *
        Pow(@BUN@, -0.170) *
        Pow(@ALBUMIN@, 0.318));

MA_GFR = GFR;
MB_GFR = GFR * 1.180;
FA_GFR = GFR * 0.762;
FB_GFR = GFR * 1.180 * 0.762;

if (("@RACE@" != "B") && ("@GENDER@" == "M"))
{
    return MA_GFR;
}
else if (("@RACE@" == "B") && ("@GENDER@" == "M"))
{
    return MB_GFR;
}
else if (("@RACE@" != "B") && ("@GENDER@" == "F"))
{
    return FA_GFR;
}
else if (("@RACE@" == "B") && ("@GENDER@" == "F"))
{
    return FB_GFR;
}
else
{
    return GFR;
}

Сгенерированный класс:

namespace Lab.ResultProcessing
{

    public sealed class ExpressionEvaluator
    {
        public double Evaluate()
        {
            double GFR;
double MA_GFR;
double MB_GFR;
double FA_GFR;
double FB_GFR;

GFR = (170 *
        System.Math.Pow(0.797258181752292, -0.999) *     
        System.Math.Pow(63.6814545438073, -0.176) *
        System.Math.Pow(5.47258181752292, -0.170) *       
        System.Math.Pow(3.79725818175229, 0.318));    

MA_GFR = GFR;                                   
MB_GFR = GFR * 1.180;                           
FA_GFR = GFR * 0.762;                           
FB_GFR = GFR * 1.180 * 0.762;                   

if (("B" != "B") && ("M" == "M"))
{
    return MA_GFR;                              
}
else if (("B" == "B") && ("M" == "M"))
{
    return MB_GFR;                              
}
else if (("B" != "B") && ("M" == "F"))
{
    return FA_GFR;                              
}
else if (("B" == "B") && ("M" == "F"))
{
    return FB_GFR;                              
}
else
{
    return GFR;
}
;
        }
    }
}

Я сейчас пытаюсь продублировать описанную выше функциональность, используя Reflection.Emit. Моя проблема в том, что у меня нет System.Reflection.TargetInvocationException: исключение было выдано целью вызова. ---> System.BadImageFormatException: неверный токен класса.

Итак, у меня есть пара вопросов:

Как можно вставить детоксинизированное пользовательское выражение, используя Reflection.Emit?
Есть ли способ увидеть код C # для испускаемого класса, или это только в IL?
Как отладить испущенный класс?

Любая помощь будет принята с благодарностью.

5
задан starblue 20 August 2010 в 09:20
поделиться