Dzisiaj krótko, acz treściwie. Jak stwierdziłem w poprzednim poście, zakres funkcjonalności DSLExecutora został ukończony – wypada więc pokazać sposób jego używania w aplikacji. Bez zbędnych wstępów przejdźmy do rzeczy.
Aby użyć DSLExecutora w aplikacji, należy:
- Zdefiniować dostępne funkcje.
- Przyjąć od użytkownika wejściowy DSL.
- Sparsować go do postaci wyrażenia.
- Otrzymane wyrażenie przekazać obiektowi klasy DSLExecutor.
Zatem po kolei:
Definicja funkcji
Jak już gdzieś wspomniałem, zależało mi na jak najwygodniejszym definiowaniu funkcji – i chyba się udało. Aby zdefiniować funkcję, wystarczy stworzyć dwie klasy:
- klasę reprezentującą sygnaturę funkcji (implementującą interfejs IFunction<TResult>), np.:
public class AddFunction : IFunction<int> { public int Addend1 { get; set; } public int Addend2 { get; set; } }
- klasę reprezentującą ciało funkcji (implementującą interfejs IFunctionHandler<TFunction, TResult>), np.:
public class AddFunctionHandler : IFunctionHandler<AddFunction, int> { public int Handle(AddFunction function) { return function.Addend1 + function.Addend2; } }
Parsowanie
(Krok drugi, czyli przyjęcie wejściowego DLSa, jest niezależny od DSLExecutora i go pomijam.)
Aby sparsować wejściowy DSL, należy stworzyć obiekt parsera i go użyć. Na tą chwilę wspierany jest tylko jeden parser: SampleDSLParser. Argumentem jego konstruktora jest lista przykładów funkcji (biblioteki, w których znajdują się przykłady zostaną przeskanowane w poszukiwaniu wszystkich dostępnych funkcji).
Po skonstruowaniu obiektu SampleDSLParser należy użyć jego metody Parse. Przykład:
var functionTypeSamples = new[] { typeof(AddFunction) }; var parser = new SampleDSLParser(functionTypeSamples); var expression = parser.Parse(dsl);
Wykonanie wyrażenia
I ostatni krok. Aby wykonać wyrażenie otrzymane w wyniku parsowania, należy stworzyć obiekt klasy DSLExecutor i użyć jego metody ExecuteExpression. W chwili obecnej konstruktor tej klasy przyjmuje słownik [typ funkcji -> typ jej handlera]. Przykład:
var functionToHandlerMap = new Dictionary<Type, Type> { [typeof(AddFunction)] = typeof(AddFunctionHandler) }; var dslExecutor = new DSLExecutor(functionToHandlerMap); var result = dslExecutor.ExecuteExpression(expression);
I gotowe! Wejściowy DSL został sparsowany i wykonany. Zachęcam do samodzielnego wypróbowania DSLExecutora (potrzebne paczki dostępne są na NuGecie: tu i tu). A ja tymczasem wracam do tworzenia przykładowej aplikacji zbierającej do kupy wszystkie zaimplementowane funkcjonalności. Cierpliwości