Я работаю над проектом для оценки токенизированных пользовательских выражений различной сложности, используя 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?
Как отладить испущенный класс?
Любая помощь будет принята с благодарностью.