저는 C#을 스크립팅 언어로 사용하여 토큰 화 된 다양한 사용자 정의 표현식을 평가하는 프로젝트를 진행하고 있습니다.어떻게 Reflection.Emit을 사용하여 리터럴 식을 삽입 할 수 있습니까?
나는 Evaluator 클래스를 생성하고 어셈블리를 생성 및로드하고 (GenerateInMemory = true) CodeDOM 및 리플렉션을 사용하여 클래스를 인스턴스화하고 평가 메서드를 실행하는 작업 모델을 사용합니다. 그러나 AppDomain에 어셈블리를로드하여 실행이 완료되면 언로드 할 수 있습니다. 이 문제를 연구하는 동안 AppDomain.DefineDynamicAssembly 메서드로 이동했습니다. 이것은 소장품 조립품을 만들 수 있기 때문에 제가 필요로하는 것 같습니다. 여기
은 사용자 정의 식의 몇 가지 예이며, 클래스 내 CodeDOM을 프로젝트에 의해 생성 :간단한 사용자 정의 표현 :
return Abs(@[email protected]/@[email protected] * 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(@[email protected], -0.999) *
Pow(@[email protected], -0.176) *
Pow(@[email protected], -0.170) *
Pow(@[email protected], 0.318));
MA_GFR = GFR;
MB_GFR = GFR * 1.180;
FA_GFR = GFR * 0.762;
FB_GFR = GFR * 1.180 * 0.762;
if (("@[email protected]" != "B") && ("@[email protected]" == "M"))
{
return MA_GFR;
}
else if (("@[email protected]" == "B") && ("@[email protected]" == "M"))
{
return MB_GFR;
}
else if (("@[email protected]" != "B") && ("@[email protected]" == "F"))
{
return FA_GFR;
}
else if (("@[email protected]" == "B") && ("@[email protected]" == "F"))
{
return FB_GFR;
}
else
{
return GFR;
}
012 3,516,
생성 된 클래스 :
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를를 사용하여 위에서 설명한 기능을 복제하려고 시도하고있다. 내 문제는 내가 detokenized 수식을 방출 클래스에 삽입하는 방법을 찾지 못했다는 것입니다. 여기
내가 사용하고있는 코드입니다 시스템 :시험 방법 ResultCalculatorTest.ResultCalculatorClassFactoryTest.DynamicEvaluate2Test는 예외를 던진 다음 methodInfo.Invoke 방법 나는 다음과 같은 오류라고
public static object DynamicEvaluate2(string expression)
{
AssemblyName assemblyName = new AssemblyName("Lab.ResultProcessing");
AppDomain appDomain = AppDomain.CurrentDomain;
AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndCollect);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name);
TypeBuilder typeBuilder = moduleBuilder.DefineType("ExpressionEvaluator", TypeAttributes.Sealed);
MethodBuilder methodBuilder = typeBuilder.DefineMethod("Evaluate", MethodAttributes.Public | MethodAttributes.Final, typeof(double), null);
ILGenerator methodGenerator = methodBuilder.GetILGenerator();
methodGenerator.Emit(OpCodes.Ldobj, expression);
methodGenerator.Emit(OpCodes.Ret);
Type evaluatorType = typeBuilder.CreateType();
MethodInfo methodInfo = evaluatorType.GetMethod("Evaluate");
object evaluator = Activator.CreateInstance(evaluatorType);
object result = methodInfo.Invoke(evaluator, null);
return result;
}
. Reflection.TargetInvocationException : 호출 타겟에 의해 예외가 Throw되었습니다. ---> System.BadImageFormatException : 클래스 토큰이 잘못되었습니다.
방법에 Reflection.Emit를를 사용하여 detokenized 사용자 정의 표현을 삽입 할 수 있습니다
그래서 나는 몇 가지 질문이 있습니까?방출 된 클래스의 C# 코드를 볼 수있는 방법이 있습니까? 아니면 IL에서만입니까?
방출 된 클래스를 어떻게 디버깅합니까?
도움을 주시면 감사하겠습니다.
'표현식'문자열이란 무엇입니까? –
표현 문자열은 "return Abs (@HDL @/@ LDL @ * 5.5);"와 같은 위에 나열된 예와 비슷합니다. 그러나 훨씬 더 복잡 할 수 있습니다. –
자신의 AppDomain과 함께 CodeDom을 사용할 수 있습니다 - CodeDom은 AppDomain으로로드 할 수있는 실제 .dll을 출력합니다. (예를 들어, 사용자의 예에서 별도의 AppDomain을 사용하지 않고 있습니다.) –