사용자가 임의의 식을 입력 할 수있는 라이브러리 작업을하고 있습니다. 그런 다음 내 라이브러리는 위의 표현식을 델리게이트로 컴파일합니다. 자, 아직 알려지지 않은 이유로 Compile
을 사용하여 표현식을 컴파일하는 경우가 종종 있습니다. 컴파일 된 표현식이 아닌 경우보다 훨씬 느린 코드가 생성됩니다. I asked a question about this 전에 한 가지 해결 방법은 Compile
이 아니라 CompileToMethod
을 사용하지 않고 새로운 동적 어셈블리의 새 형식에 static
메서드를 만드는 것입니다. 그건 효과가 있고 코드는 빠릅니다..NET : 동적 어셈블리에서 비공개 멤버에 액세스
그러나 사용자가 임의의 식을 입력 할 수 있으며 사용자가 비공개 함수를 호출하거나 식에서 비공개 필드에 액세스하면 System.MethodAccessException
을 throw합니다 (비공개 메서드의 경우) 대리자가 호출 될 때
는 내가 아마 여기에 할 수있는 것은 표현 아무것도 아닌 대중과 이러한 경우에 Compile
느린을 사용하여 액세스하는 경우 확인하는 새로운 ExpressionVisitor
을 만드는 것입니다,하지만 난 오히려 동적 어셈블리가 어떻게 든 액세스 권한을 얻을 수 있음을 가질 것 비공개 회원. 아니면 내가 할 수있는 일이 있다면 Compile
(때때로) 느려지는지 확인하십시오.
전체 코드
이 문제를 재현하는 방법 :using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
namespace DynamicAssembly
{
public class Program
{
private static int GetValue()
{
return 1;
}
public static int GetValuePublic()
{
return 1;
}
public static int Foo;
static void Main(string[] args)
{
Expression<Func<int>> expression =() => 10 + GetValue();
Foo = expression.Compile()();
Console.WriteLine("This works, value: " + Foo);
Expression<Func<int>> expressionPublic =() => 10 + GetValuePublic();
var compiledDynamicAssemblyPublic = (Func<int>)CompileExpression(expressionPublic);
Foo = compiledDynamicAssemblyPublic();
Console.WriteLine("This works too, value: " + Foo);
var compiledDynamicAssemblyNonPublic = (Func<int>)CompileExpression(expression);
Console.WriteLine("This crashes");
Foo = compiledDynamicAssemblyNonPublic();
}
static Delegate CompileExpression(LambdaExpression expression)
{
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("MyAssembly"+ Guid.NewGuid().ToString("N")),
AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
var typeBuilder = moduleBuilder.DefineType("MyType", TypeAttributes.Public);
var methodBuilder = typeBuilder.DefineMethod("MyMethod",
MethodAttributes.Public | MethodAttributes.Static);
expression.CompileToMethod(methodBuilder);
var resultingType = typeBuilder.CreateType();
var function = Delegate.CreateDelegate(expression.Type,
resultingType.GetMethod("MyMethod"));
return function;
}
}
}
답변이 없지만 개인용 메서드 호출을 지원해야하는 이유는 무엇입니까? – jlew
사용자가 가능해야하기 때문에. '() => CallPrivateMethod()'와 같이 식을 생성 할 때 * 액세스 할 수 있기 때문에 런타임에 실패합니다. 그에게 달리기 전까지는 작동하지 않으며 충돌하고 화상을 입는다는 것을 나타내는 것은 아무것도 없습니다. 그건 정말 나쁘고 "최소한의 놀라움"에 대한 규칙을 어기므로 그렇게하는 것이 정당화 될 수 없으며 느린 코드에 정착해야합니다. – JulianR
사용자가 C# 프로그래머 인 경우 (예 : 양식에 표현식을 입력하는 것과는 대조적으로) 의미가 있습니다. 컴파일 된 델리게이트에 대한 릴리즈와 디버깅 모드를 벤치마킹 해 보았습니까? 그들은 어떻게 서로 비교합니까? – jlew