우리는 복잡하고 풍부한 데스크톱 애플리케이션을 작성하고 있으며보고 형식에 유연성을 제공해야하므로 개체 모델을 스크립팅 언어에 노출시킬 것이라고 생각했습니다. 시간은 VBA (여전히 옵션 임)를 의미했지만 관리 코드 파생 VSTA (내 생각에)는 포도 나무에서 시들해진 것 같습니다.
이제 Windows .NET에서 임베디드 스크립팅 언어에 가장 적합한 선택은 무엇입니까?
우리는 복잡하고 풍부한 데스크톱 애플리케이션을 작성하고 있으며보고 형식에 유연성을 제공해야하므로 개체 모델을 스크립팅 언어에 노출시킬 것이라고 생각했습니다. 시간은 VBA (여전히 옵션 임)를 의미했지만 관리 코드 파생 VSTA (내 생각에)는 포도 나무에서 시들해진 것 같습니다.
이제 Windows .NET에서 임베디드 스크립팅 언어에 가장 적합한 선택은 무엇입니까?
답변:
개인적으로 C #을 스크립팅 언어로 사용합니다. .NET 프레임 워크 (및 Mono, Matthew Scharley 덕분에)는 실제로 프레임 워크 자체에 각 .NET 언어에 대한 컴파일러를 포함합니다.
기본적으로이 시스템의 구현에는 두 부분이 있습니다.
사용자가 코드를 컴파일하도록 허용 이것은 비교적 쉽고 몇 줄의 코드로만 수행 할 수 있습니다 (사용 방법에 따라 수십 줄의 코드가 추가 될 수있는 오류 대화 상자를 추가 할 수도 있지만 당신은 그것을 원합니다).
컴파일 된 어셈블리에 포함 된 클래스 생성 및 사용 이것은 이전 단계보다 약간 더 어렵습니다 (약간의 반영이 필요함). 기본적으로 컴파일 된 어셈블리를 프로그램의 "플러그인"으로 취급해야합니다. C #으로 플러그인 시스템을 만들 수있는 다양한 방법에 대한 튜토리얼이 꽤 많이 있습니다 (Google은 당신의 친구입니다).
이 시스템을 구현하는 방법을 보여주기 위해 "빠른"응용 프로그램을 구현했습니다 (2 개의 작업 스크립트 포함!). 이것은 응용 프로그램에 대한 완전한 코드입니다. 새 코드를 만들고 "program.cs"파일에 코드를 붙여 넣으면됩니다. 이 시점에서 나는 내가 붙여 넣을 코드의 큰 덩어리에 대해 사과해야한다. (나는 그것이 그렇게 큰 것을 의도하지 않았지만 내 주석에 약간 빠져 들었다)
using System;
using System.Windows.Forms;
using System.Reflection;
using System.CodeDom.Compiler;
namespace ScriptingInterface
{
public interface IScriptType1
{
string RunScript(int value);
}
}
namespace ScriptingExample
{
static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
// Lets compile some code (I'm lazy, so I'll just hardcode it all, i'm sure you can work out how to read from a file/text box instead
Assembly compiledScript = CompileCode(
"namespace SimpleScripts" +
"{" +
" public class MyScriptMul5 : ScriptingInterface.IScriptType1" +
" {" +
" public string RunScript(int value)" +
" {" +
" return this.ToString() + \" just ran! Result: \" + (value*5).ToString();" +
" }" +
" }" +
" public class MyScriptNegate : ScriptingInterface.IScriptType1" +
" {" +
" public string RunScript(int value)" +
" {" +
" return this.ToString() + \" just ran! Result: \" + (-value).ToString();" +
" }" +
" }" +
"}");
if (compiledScript != null)
{
RunScript(compiledScript);
}
}
static Assembly CompileCode(string code)
{
// Create a code provider
// This class implements the 'CodeDomProvider' class as its base. All of the current .Net languages (at least Microsoft ones)
// come with thier own implemtation, thus you can allow the user to use the language of thier choice (though i recommend that
// you don't allow the use of c++, which is too volatile for scripting use - memory leaks anyone?)
Microsoft.CSharp.CSharpCodeProvider csProvider = new Microsoft.CSharp.CSharpCodeProvider();
// Setup our options
CompilerParameters options = new CompilerParameters();
options.GenerateExecutable = false; // we want a Dll (or "Class Library" as its called in .Net)
options.GenerateInMemory = true; // Saves us from deleting the Dll when we are done with it, though you could set this to false and save start-up time by next time by not having to re-compile
// And set any others you want, there a quite a few, take some time to look through them all and decide which fit your application best!
// Add any references you want the users to be able to access, be warned that giving them access to some classes can allow
// harmful code to be written and executed. I recommend that you write your own Class library that is the only reference it allows
// thus they can only do the things you want them to.
// (though things like "System.Xml.dll" can be useful, just need to provide a way users can read a file to pass in to it)
// Just to avoid bloatin this example to much, we will just add THIS program to its references, that way we don't need another
// project to store the interfaces that both this class and the other uses. Just remember, this will expose ALL public classes to
// the "script"
options.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
// Compile our code
CompilerResults result;
result = csProvider.CompileAssemblyFromSource(options, code);
if (result.Errors.HasErrors)
{
// TODO: report back to the user that the script has errored
return null;
}
if (result.Errors.HasWarnings)
{
// TODO: tell the user about the warnings, might want to prompt them if they want to continue
// runnning the "script"
}
return result.CompiledAssembly;
}
static void RunScript(Assembly script)
{
// Now that we have a compiled script, lets run them
foreach (Type type in script.GetExportedTypes())
{
foreach (Type iface in type.GetInterfaces())
{
if (iface == typeof(ScriptingInterface.IScriptType1))
{
// yay, we found a script interface, lets create it and run it!
// Get the constructor for the current type
// you can also specify what creation parameter types you want to pass to it,
// so you could possibly pass in data it might need, or a class that it can use to query the host application
ConstructorInfo constructor = type.GetConstructor(System.Type.EmptyTypes);
if (constructor != null && constructor.IsPublic)
{
// lets be friendly and only do things legitimitely by only using valid constructors
// we specified that we wanted a constructor that doesn't take parameters, so don't pass parameters
ScriptingInterface.IScriptType1 scriptObject = constructor.Invoke(null) as ScriptingInterface.IScriptType1;
if (scriptObject != null)
{
//Lets run our script and display its results
MessageBox.Show(scriptObject.RunScript(50));
}
else
{
// hmmm, for some reason it didn't create the object
// this shouldn't happen, as we have been doing checks all along, but we should
// inform the user something bad has happened, and possibly request them to send
// you the script so you can debug this problem
}
}
else
{
// and even more friendly and explain that there was no valid constructor
// found and thats why this script object wasn't run
}
}
}
}
}
}
}
csscript.net
이것에 대한 일종의 래퍼처럼 보입니다. 이것은 기본적으로 베어 본 구현입니다. 더 나은 질문은 "이것이 아닌 csscript.net이 나를 위해 무엇을 하는가"일 것입니다. 나는 csscript가 무엇을하는지 모르지만, 그들은 위의 코드가 무엇을하는지 확실히 알고 있습니다. 그들은 라이브러리에 그것을 가지고 있습니다.
IronPython . 삽입 방법에 대한 개요는 다음과 같습니다 .
PowerShell 엔진은 스크립트가 가능하도록 응용 프로그램에 쉽게 포함되도록 설계되었습니다. 실제로 PowerShell CLI는 엔진에 대한 텍스트 기반 인터페이스입니다.
편집 : https://devblogs.microsoft.com/powershell/making-applications-scriptable-via-powershell/ 참조
부 언어.
왜 C #을 사용해 보지 않겠습니까? Mono에는 특히 C #을 동적으로 평가하기위한 멋진 새 프로젝트가 있습니다.
위에서 언급 한대로 IronRuby. C # 프로그래머로서 저에게 흥미로운 프로젝트 는 Mono의 C # Eval 지원입니다 . 그러나 아직 사용할 수 없습니다 (Mono 2.2의 일부가 될 것입니다).
현재 유지하고있는 S # 을 제안 할 수 있습니다 . C #으로 작성되고 .NET 애플리케이션 용으로 설계된 오픈 소스 프로젝트입니다.
처음에는 (2007-2009) http://www.codeplex.com/scriptdotnet 에서 호스팅 되었지만 최근에는 github로 이동했습니다.
나는 이것을 아직 시도하지 않았지만 꽤 멋지다.
방금 클라이언트 용 플러그인을 만들어 VBA가 Office에서하는 것처럼 작동하는 모듈에 C # 코드를 작성할 수 있도록했습니다.
나는 전에 Lua 를 사용했습니다 . Delphi 앱에 있지만 많은 것들에 포함될 수 있습니다. Adobe의 Photoshop Lightroom 에서 사용됩니다 .
저는 C # 자체로 스크립팅하는 것을 좋아합니다 . 이제 2013 년에는 C # 스크립팅에 대한 상당히 좋은 지원이 제공되며 점점 더 많은 라이브러리를 사용할 수있게되었습니다.
Mono는 스크립트 C # 코드에 대한 훌륭한 지원을 제공 Mono.CSharp.dll
하며 응용 프로그램에를 포함하여 .NET과 함께 사용할 수 있습니다 . 내가 만든 C # 스크립팅 응용 프로그램의 경우 CShell을 확인하십시오.
또한 Microsoft 에서 제공하는 Roslyn 의`ScriptEngine '을 확인하십시오 . 그러나 이것은 CTP 일뿐입니다.
일부 사람들이 이미 언급했듯이 CS-Script 도 꽤 오랫동안 사용되었습니다.