.NET 애플리케이션에 스크립팅 기능 추가
C #으로 작성된 작은 게임이 있습니다. 데이터베이스를 백엔드로 사용합니다. 그것은이다 트레이딩 카드 게임 , 내가 스크립트로 카드의 기능을 구현하고 싶었다.
내 말은 본질적 ICard
으로 카드 클래스가 ( public class Card056: ICard
)를 구현 하고 게임에서 호출하는 함수를 포함 하는 인터페이스가 있다는 것 입니다.
이제 유지 / 수정 가능하게 만들기 위해 각 카드의 클래스를 데이터베이스의 소스 코드로 사용하고 기본적으로 처음 사용할 때 컴파일하고 싶습니다. 따라서 카드를 추가 / 변경해야 할 때 어셈블리를 배포 할 필요없이 데이터베이스에 추가하고 애플리케이션을 새로 고치도록 지시합니다 (특히 카드 당 하나의 어셈블리에 대해 이야기 할 것이므로 수백 개의 어셈블리를 의미 함). .
가능합니까? 소스 파일에서 클래스를 등록한 다음 인스턴스화합니다.
ICard Cards[current] = new MyGame.CardLibrary.Card056();
Cards[current].OnEnterPlay(ref currentGameState);
언어는 C #이지만 모든 .NET 언어로 스크립트를 작성할 수 있다면 추가 보너스입니다.
Oleg Shilo의 C # 스크립트 솔루션 (The Code Project에서 )은 실제로 애플리케이션에서 스크립트 기능을 제공하는 훌륭한 소개입니다.
다른 접근 방식은 IronRuby , IronPython 또는 Lua 와 같이 스크립팅을 위해 특별히 구축 된 언어를 고려하는 것 입니다.
IronPython과 IronRuby는 모두 현재 사용할 수 있습니다.
IronPython 포함에 대한 가이드 는 10 단계로 기존 앱에 IronPython 스크립트 지원을 포함하는 방법을 참조하세요 .
Lua는 게임에서 일반적으로 사용되는 스크립팅 언어입니다. CodePlex- http ://www.codeplex.com/Nua에서 구할 수있는 .NET 용 Lua 컴파일러가 있습니다 .
이 코드베이스는 .NET에서 컴파일러를 빌드하는 방법을 배우고 싶다면 훌륭한 읽기입니다.
완전히 다른 각도는 PowerShell을 사용하는 것 입니다. 애플리케이션에 PowerShell을 포함하는 수많은 예제가 있습니다. 여기에 Powershell Tunnel 주제에 대한 철저한 프로젝트가 있습니다.
IronRuby를 사용할 수 있습니다.
그렇지 않으면 미리 컴파일 된 어셈블리를 배치하는 디렉터리가있는 것이 좋습니다. 그런 다음 DB에서 어셈블리 및 클래스에 대한 참조를 갖고 리플렉션을 사용하여 런타임에 적절한 어셈블리를로드 할 수 있습니다.
런타임에 컴파일하려면 CodeDOM을 사용하고 리플렉션을 사용하여 동적 어셈블리를로드 할 수 있습니다. 도움이 될 수있는 Microsoft 문서 문서 .
DLR을 사용하지 않으려면 Boo (인터프리터가 있음)를 사용 하거나 CodePlex의 Script.NET (S #) 프로젝트를 고려할 수 있습니다. Boo 솔루션을 사용하면 컴파일 된 스크립트 또는 인터프리터 사용 중에서 선택할 수 있으며 Boo는 멋진 스크립팅 언어를 만들고 개방형 컴파일러 아키텍처를 통해 유연한 구문과 확장 가능한 언어를 제공합니다. 하지만 Script.NET도 멋지게 보이며 해당 언어와 오픈 소스 프로젝트를 쉽게 확장 할 수 있으며 매우 친숙한 Compiler Generator ( Irony.net )를 사용합니다.
자신의 스크립팅 플랫폼을 정말 쉽게 호스팅 할 수있는 방법을 제공하는 DLR 언어를 사용할 수 있습니다. 그러나이를 위해 스크립팅 언어를 사용할 필요는 없습니다. C #을 사용하고 C # 코드 공급자로 컴파일 할 수 있습니다. 자체 AppDomain에로드하는 한 마음의 콘텐츠에로드 및 언로드 할 수 있습니다.
Nua가 완전하지 않고 매우 유용한 기능 (코 루틴 등)을 구현하지 않는 것으로 보이는 Lua를 완전히 구현했기 때문에 LuaInterface 를 사용하는 것이 좋습니다 .
외부에 미리 포장 된 Lua 모듈 중 일부를 사용하려면 완전히 관리되는 코드를 빌드하고 필요한 C API를 노출 할 수없는 2.x 시리즈와 달리 1.5.x 라인을 따라 무언가를 사용하는 것이 좋습니다.
NET 1.1 응용 프로그램에 LuaInterface1.3 + Lua 5.0을 사용하고 있습니다.
Boo의 문제는 즉시 코드를 구문 분석 / 컴파일 / 평가할 때마다 boo 클래스 집합을 생성하므로 메모리 누수가 발생한다는 것입니다.
반면에 Lua는 그렇게하지 않으므로 매우 안정적이며 훌륭하게 작동합니다 (C #에서 Lua로 객체를 거꾸로 전달할 수 있음).
지금까지 아직 PROD에 넣지 않았지만 매우 유망 해 보입니다.
LuaInterface + Lua 5.0을 사용하여 PROD에서 메모리 누수 문제가 있었 으므로 Lua 5.2를 사용하고 DllImport를 사용하여 C #에 직접 연결했습니다. 메모리 누수는 LuaInterface 라이브러리 내부에있었습니다.
Lua 5.2 : http://luabinaries.sourceforge.net 및 http://sourceforge.net/projects/luabinaries/files/5.2/Windows%20Libraries/Dynamic/lua-5.2_Win32_dll7_lib.zip/download에서
이 작업을 수행하면 모든 메모리 누수가 사라지고 응용 프로그램이 매우 안정적이었습니다.
내 부서에서 판매하는 주요 응용 프로그램은 클라이언트 사용자 지정을 제공하기 위해 매우 유사한 작업을 수행합니다 (즉, 소스를 게시 할 수 없음). 동적 VB.NET 스크립트를로드하는 C # 응용 프로그램이 있습니다 (모든 .NET 언어를 쉽게 지원할 수 있지만 사용자 지정 팀이 ASP 배경에서 왔기 때문에 VB가 선택되었습니다).
.NET의 CodeDom을 사용하여 VB를 사용하여 데이터베이스에서 스크립트를 컴파일합니다 CodeDomProvider
(귀찮게도 기본적으로 .NET 2로 설정됩니다. 3.5 기능을 지원하려면 "CompilerVersion"= "v3.5"로 사전을 생성자에 전달해야합니다. ). CodeDomProvider.CompileAssemblyFromSource
메서드를 사용하여 컴파일합니다 (설정을 전달하여 메모리에서만 컴파일되도록 할 수 있습니다.
이로 인해 메모리에 수백 개의 어셈블리가 생성되지만 모든 동적 클래스의 코드를 단일 어셈블리에 통합하고 변경이있을 때 전체 로트를 다시 컴파일 할 수 있습니다. 이것은 테스트 할 때 PDB 를 사용하여 디스크에서 컴파일 할 플래그를 추가 할 수 있다는 장점이 있으며 동적 코드를 통해 디버깅 할 수 있습니다.
예, 그것에 대해 생각했지만 곧 또 다른 DSL (Domain-Specific-Language)이 너무 많을 것이라는 것을 알게되었습니다.
본질적으로 그들은 예측할 수없는 방식으로 내 게임 상태와 상호 작용해야합니다. 예를 들어, 카드에는 "이 카드가 플레이에 들어가면 모든 언데드 하수인이 비행하는 적에 대해 +3 공격을 얻습니다. 단, 적이 축복받은 경우는 예외입니다."라는 규칙이있을 수 있습니다. 트레이딩 카드 게임은 턴 기반이므로 GameState Manager는 OnStageX 이벤트를 실행하고 카드가 필요한 방식으로 다른 카드 또는 GameState를 수정할 수 있도록합니다.
DSL을 만들려고하면 상당히 큰 기능 집합을 구현하고 지속적으로 업데이트해야하므로 실제로 제거하지 않고 유지 관리 작업을 다른 부분으로 전환해야합니다.
이것이 바로 이벤트를 발생시키고 카드가 어떤 방식 으로든 (코드 액세스 보안의 한계 내에서) 게임 상태를 조작 할 수 있도록 "실제".NET 언어를 유지하고 싶었던 이유입니다.
다음 버전의 .NET (5.0?)은 직접 스크립트 평가를 가능하게하는 "서비스로서의 컴파일러"를 여는 것에 대해 많은 논의를했습니다.
참고 URL : https://stackoverflow.com/questions/260/adding-scripting-functionality-to-net-applications
'Program Tip' 카테고리의 다른 글
unique_ptr은 이동 후 nullptr을 저장하도록 보장됩니까? (0) | 2020.10.30 |
---|---|
시계없는 컴퓨터 칩은 어떻게 되었습니까? (0) | 2020.10.30 |
주어진 선택기와 일치하는 부모가있는 항목을 제외하는 JQuery 선택기는 무엇입니까? (0) | 2020.10.29 |
Rails ActiveRecord : INNER JOIN 대신 LEFT JOIN으로 조인합니다. (0) | 2020.10.29 |
MSTest를 사용하여 비동기 코드를 테스트하는 방법 (0) | 2020.10.29 |