2010-03-16 3 views
6

유전자 프로그램을 만들고 있지만 알고리즘에 새로운 기능을 표시하려는 C#으로 제한을 치고 있지만이를 다시 컴파일하지 않고는 할 수 없습니다. 프로그램. 본질적으로 나는 프로그램의 사용자가 허용 된 기능을 제공하기를 원하며 GP는 자동으로 그 기능을 사용할 것이다. 사용자가 프로그래밍에 대해 가능한 한 알 필요가 있으면 좋을 것입니다.C# 런타임에서 해석되는 함수를 만드는 방법

새 기능을 프로그램에 컴파일하지 않고 플러그인하려고합니다. 파이썬에서는 이것이 모두 해석 되었기 때문에 쉽습니다. 그러나 C#으로 어떻게해야하는지 전혀 모르겠습니다. 아무도 C#에서 이것을 달성하는 방법을 알고 있습니까? 도서관, 기술 등이 있습니까?

+2

이 질문에 대한 답변이 충분하지 않지만, .net을 사용하고 있기 때문에 런타임에 해석 할 수 있으므로 앱의 해당 부분에 F #을 사용할 수 있습니다. – andy

답변

13

이것은 프로그램 사용자가 "허용 된 기능 제공"방법에 따라 다릅니다.

  • 사용자가 이미 구현 한 기능을 선택하는 경우 위임자 또는 표현식 트리로 전달할 수 있습니다.
  • 사용자가 자신의 메서드를 C# 또는 다른 .NET 언어로 작성하고 어셈블리로 컴파일하려고하면 Reflection을 사용하여 메서드를로드 할 수 있습니다.
  • 사용자가 C# 소스 코드를 프로그램에 입력 할 수있게하려면 CodeDom을 사용하여 해당 코드를 컴파일 한 다음 Reflection을 사용하여 결과 어셈블리를 호출 할 수 있습니다.
  • 사용자에게 맞춤 표현식 언어를 제공하려는 경우 (예 : 간단한 수학 언어라면 (언어를 파싱 할 수 있다고 가정하면) Reflection.Emit을 사용하여 동적 어셈블리를 생성하고이를 리플렉션을 사용하여 호출 할 수 있습니다. 또는 사용자 코드에서 표현식 트리를 생성하고 LINQ를 사용하여이를 컴파일 할 수 있습니다. 얼마나 많은 유연성이 필요한지에 달려 있습니다. (기다릴 여유가 있다면 .NET 4.0의 표현 트리가 3.5에 있던 많은 제한을 제거하므로 Reflection.Emit을 피할 수 있습니다.)
  • 사용자가 입력하기를 원한다면 Python, Ruby 또는 다른 DLR 언어를 사용하는 표현식을 사용하면 사용자의 코드를 해석 할 동적 언어 런타임을 호스팅 할 수 있습니다.

DLR (및 IronPython 또는 IronRuby) 호스팅은 잘 테스트 된 환경과 DLR이 제공하는 모든 최적화 기능을 갖추기 때문에 좋은 선택 일 수 있습니다.Here's a how-to using IronPython.

성능 질문에 대한 답변으로 추가되었습니다. DLR은 최적화에 대해 상당히 현명합니다. 매번 소스 코드를 맹목적으로 다시 해석하지는 않습니다. 일단 소스 코드 (또는 특정 함수 또는 클래스)가 MSIL로 변환되면 소스 코드가 변경 될 때까지 컴파일 된 표현을 계속 재사용합니다 (예 : 함수가 재정의되었습니다). 따라서 사용자가 동일한 기능을 계속 사용하지만 다른 데이터 세트를 계속 사용하는 경우 동일한 ScriptScope를 유지할 수 있다면 괜찮은 성능을 얻을 수 있습니다. 당신의 관심사가 유전자 알고리즘 중에 같은 기능을 반복 실행한다면 바로 그런 것입니다. DLR을 호스팅하는 것은 매우 쉽기 때문에 개념 증명 및 측정이 자신의 필요에 부합하는지 확인하는 것이 어렵지 않습니다.

+0

내가 언급 한 리플렉션 옵션을 좋아합니다 ... 내 최고의 옵션 일 수 있습니다. DLR이 좋은 대안 일 수 있습니다. DLR 메소드를 호출 할 때 상당한 성능 오버 헤드가 있습니까? 메소드는 매우 빈번하게 호출 될 것이므로 가능한 한 적은 오버 헤드가있는 옵션을 활용하고 싶습니다. – Kiril

+0

DLR이 반복적으로 호출되는 코드로 성능을 향상시키는 방법에 대한 정보를 추가했습니다. 양적 수치는 없지만 Google에서 뭔가를 찾거나 DLR을 호스팅하고 빠르게 진행하는 것이 쉽지 않을 수도 있습니다. – itowlson

+0

그래, 나는 실행하는 동안 소스 코드를 수정할 계획이 없다. 아마 DLR이 다른 대안이 될 수 있기 때문에 다른 데이터 인스턴스와 같은 방법이 될 것이다. 나는 또한 memoization을 활용할 것이기 때문에 동일한 매개 변수가 항상 동일한 결과를 생성한다면 메서드는 불필요하게 실행되지 않습니다. 감사 :). – Kiril

7

Expression Trees을 만들고 조작 할 수 있습니다. 표현식 트리를 평가하려면 Linq을 사용하십시오.

+2

표현식 트리가 많이 있습니다. 순수 eval 함수보다 더 나은 경로. –

+0

GP에는 여러 개인이 있으며 각 개인은 기능과 상수의 트리를 가지고 있습니다. 트리의 노드는 함수 또는 상수 일 수 있습니다. 즉, 주어진 노드의 함수를 표현식 트리로 대체해야합니까? 사용자가 기능을 어떻게 플러그인 할 수 있습니까? – Kiril

+0

트리는 실제로 함수를 포함하지는 않지만 함수를 식별하는 enum을 포함한다는 점에 유의하십시오. "executor"라고 불리면 enum을보고 해당 함수를 호출합니다. – Kiril

1

코드 내에서 컴파일러에 액세스 할 수 있으므로 컴파일 된 코드의 인스턴스를 만들고 응용 프로그램을 다시 시작하지 않고 사용할 수 있습니다. 이

Here

Here

두 번째 주위의 예는 자바 스크립트 평가자는되어 있지만 충분히 쉽게 적용 할 수있다.

1

IL 수준에서 코드를 생성하려면 System.Reflection.Emit을 살펴보십시오.

또는 C#을 생성하고 라이브러리로 컴파일하고 동적으로로드하십시오. 거의 융통성이 없습니다.