W poprzednim wpisie, w dużym skrócie przedstawiłem po co powstał Roslyn i komu może przydać się. W kilku kolejnych postach, zaprezentuję w praktyce jego najważniejsze funkcje.
Zaczynami od scripting API. APi szczególnie przydatne w przypadku edytorów do gier czy bardziej zaawansowanych reguł biznesowych. Zacznijmy od klasycznego “hello world”:
CSharpScript.Run("System.Console.WriteLine(\"Hello world\")");
Nie trudno domyślić się, że Run wykona kod przekazany jako String – w tym przypadku jest to po prostu wyświetlenie napisu na ekranie.
Zwykle chcemy jednak zmodyfikować jakieś zmienne:
ScriptState result=CSharpScript.Run("int a=5;int b=5; int c=a+b;"); foreach (ScriptVariable scriptVariable in result.Variables) { Console.WriteLine(string.Format("{0}:{1}", scriptVariable.Name, scriptVariable.Value)); }
Pole Variable będzie zawierać wszelkie zmienne stworzone w skrypcie, wraz z ich wartościami. W tym przypadku będzie to “a:5,b:5,c:10”.
Możliwe jest również przekazywanie parametrów do skryptu. Stwórzmy dowolną strukturę:
public class Data { public int Number = 5; }
Następnie wykonanie skryptu będzie wyglądać następująco:
var data = new Data(); CSharpScript.Run("Number=Number*2", data); Console.WriteLine(data.Number);
Zmienna Number zostanie przekazana z wartością 5, a potem w skrypcie zostanie zmieniona na 10 i zwrócona na zewnątrz. W skrócie jest to argument wejściowo-wyjściowy.
Inna przydatna funkcja to Eval. Uruchamia ona po prostu skrypt i zwraca od razu to co znajduje się w nim na wyjściu. Na przykład, poniższy kod zwróci losowo wygenerowaną liczbę:
object result = CSharpScript.Eval("new Random().Next()"); Console.WriteLine(result.ToString());
To samo można oczywiście osiągnąć za pomocą Run, ale Eval w wielu sytuacjach jest bardziej intuicyjny w użyciu. Zarówno do Eval jak i Run można przekazać ScriptOptions. Bardzo często skrypty potrzebują referencji do zewnętrznych bibliotek i wtedy możemy:
ScriptOptions options = ScriptOptions.Default .AddReferences(Assembly.GetAssembly(typeof(Path))) .AddNamespaces("System.IO"); var currentDir = CSharpScript.Eval(@"Path.GetCurrentDirectory()", options);
Bardzo ciekawą opcją jest skompilowanie skryptu i użycie potem go jako zwykłej delegaty:
ScriptState state = CSharpScript.Run("int Add(int x,int y) { return x +y; }"); var add = state.CreateDelegate<Func<int, int,int>>("Add"); var sum = add(5, 10); Console.Write(sum); // 15
Hej Piotrek,
Wiesz moze czy jest z Roslynem mozliwosc wczytania i modyfikacja on the fly juz istniejacego assembly ?
Czesc,
Z tego co wiem – nie, dlatego tworze zawsze osobny AppDomain jak mam jais kod do skompilowania i wykonania.