|
1 | | -# Welcome to Hyperbee Expressions Interpreter |
| 1 | +# Welcome to Hyperbee Expressions |
2 | 2 |
|
3 | | -`Hyperbee.Expressions.Interpreter` is a C# library that extends the capabilities of expression trees to run without compilation. |
| 3 | +`Hyperbee.Expressions` is a library for creating c# expression trees that extend the capabilities of standard expression |
| 4 | +trees to handle asynchronous workflows and other language constructs. |
4 | 5 |
|
5 | 6 | ## Features |
6 | 7 |
|
7 | | -This adds the extension method `Intrepet()` to the `LambdaExpression` class to allow for the interpretation of expression trees at runtime. |
| 8 | +* **Async Expressions** |
| 9 | + * `AwaitExpression`: An expression that represents an await operation. |
| 10 | + * `AsyncBlockExpression`: An expression that represents an asynchronous code block. |
8 | 11 |
|
9 | | -This works the same way that the built in `lambda.Compile()` does, but without the need for compilation. |
| 12 | +* **Using Expression** |
| 13 | + * `UsingExpression`: An expression that automatically disposes IDisposable resources. |
10 | 14 |
|
11 | | -Additionally it's similar to `lambda.Compile( preferInterpretation: true )` but allows for async code execution and other extension expressions. |
| 15 | +* **Looping Expressions** |
| 16 | + * `WhileExpression`: An expression that represents a while loop. |
| 17 | + * `ForExpression`: An expression that represents a for loop. |
| 18 | + * `ForEachExpression`: An expression that represents a foreach loop. |
| 19 | + |
| 20 | +* **Other Expressions** |
| 21 | + * `StringFormatExpression`: An expression that creates a string using a supplied format string and parameters. |
| 22 | + * `DebugExpression`: An expression that helps when debugging expression trees. |
| 23 | + |
| 24 | +* Supports Fast Expression Compiler (FEC) for improved performance. |
| 25 | + |
| 26 | +* Supports interpreted expression trees using `lambda.Compile(preferInterpretation: true)`. |
| 27 | + ```csharp |
| 28 | + var lambda = Expression.Lambda<Func<int>>(Expression.Constant(1)); |
| 29 | + var interpetedLambda = lambda.Compile(preferInterpretation: true); |
| 30 | + ``` |
12 | 31 |
|
13 | 32 | ## Examples |
14 | 33 |
|
| 34 | +### Asynchronous Expressions |
| 35 | + |
| 36 | +The following example demonstrates how to create an asynchronous expression tree. |
| 37 | + |
| 38 | +When the expression tree is compiled, the `AsyncBlockExpression` will auto-generate a state machine that executes |
| 39 | +`AwaitExpressions` in the block asynchronously. |
| 40 | + |
15 | 41 | ```csharp |
16 | | - var lambda = Expression.Lambda<Func<int>>(Expression.Constant(1)); |
17 | 42 |
|
18 | | - var interpetedLambda = lambda.Interpret(); |
| 43 | +public class Example |
| 44 | +{ |
| 45 | + public async Task ExampleAsync() |
| 46 | + { |
| 47 | + // Create an async block that calls async methods and assigns their results |
| 48 | + var instance = Constant( this ); |
| 49 | + var result1 = Variable( typeof(int), "result1" ); |
| 50 | + var result2 = Variable( typeof(int), "result2" ); |
| 51 | + |
| 52 | + var asyncBlock = BlockAsync( |
| 53 | + [result1, result2], |
| 54 | + Assign( result1, Await( |
| 55 | + Call( instance, nameof(FirstAsyncMethod), Type.EmptyTypes ) |
| 56 | + ) ), |
| 57 | + Assign( result2, Await( |
| 58 | + Call( instance, nameof(SecondAsyncMethod), Type.EmptyTypes, result1 ) |
| 59 | + ) ) |
| 60 | + ); |
| 61 | + |
| 62 | + // Compile and execute the async block |
| 63 | + var lambda = Lambda<Func<Task<int>>>( asyncBlock ); |
| 64 | + var compiledLambda = lambda.Compile(); |
| 65 | + var resultValue2 = await compiledLambda(); |
| 66 | + |
| 67 | + Console.WriteLine( $"Second async method result: {resultValue2}" ); |
| 68 | + } |
19 | 69 |
|
20 | | - var result = interpetedLambda(); |
| 70 | + public static async Task<int> FirstAsyncMethod() |
| 71 | + { |
| 72 | + await Task.Delay( 1000 ); // Simulate async work |
| 73 | + return 42; // Example result |
| 74 | + } |
| 75 | + |
| 76 | + public static async Task<int> SecondAsyncMethod( int value ) |
| 77 | + { |
| 78 | + await Task.Delay( 1000 ); // Simulate async work |
| 79 | + return value * 2; // Example result |
| 80 | + } |
| 81 | +} |
21 | 82 | ``` |
22 | 83 |
|
23 | | -> **Note:** Every call to the interpreted lambda will walk the expression tree to determine |
24 | | -> the correct result. In cases where the lambda is not reused this may perform better than compiling and |
25 | | -> running, but if the lambda is reused it may be better compile it once. Always profile to determine the best approach. |
| 84 | +### Using Expression |
| 85 | + |
| 86 | +The following example demonstrates how to create a Using expression. |
| 87 | + |
| 88 | +```csharp |
| 89 | +public class Example |
| 90 | +{ |
| 91 | + private class DisposableResource : IDisposable |
| 92 | + { |
| 93 | + public bool IsDisposed { get; private set; } |
| 94 | + public void Dispose() => IsDisposed = true; |
| 95 | + } |
| 96 | + |
| 97 | + public void ExampleUsing() |
| 98 | + { |
| 99 | + var resource = new TestDisposableResource(); |
| 100 | + |
| 101 | + var disposableExpression = Expression.Constant( resource, typeof( TestDisposableResource ) ); |
| 102 | + var bodyExpression = Expression.Empty(); // Actual body isn't important |
| 103 | +
|
| 104 | + var usingExpression = ExpressionExtensions.Using( |
| 105 | + disposableExpression, |
| 106 | + bodyExpression |
| 107 | + ); |
| 108 | + |
| 109 | + var compiledLambda = Expression.Lambda<Action>( reducedExpression ).Compile(); |
| 110 | + |
| 111 | + compiledLambda(); |
| 112 | + |
| 113 | + Console.WriteLine( $"Resource was disposed {resource.IsDisposed}." ); |
| 114 | + } |
| 115 | +} |
| 116 | +``` |
26 | 117 |
|
27 | 118 | ## Credits |
28 | 119 |
|
29 | 120 | Special thanks to: |
30 | 121 |
|
| 122 | +- Sergey Tepliakov - [Dissecting the async methods in C#](https://devblogs.microsoft.com/premier-developer/dissecting-the-async-methods-in-c/). |
| 123 | +- [Fast Expression Compiler](https://github.com/dadhi/FastExpressionCompiler) for improved performance. :heart: |
31 | 124 | - [Just The Docs](https://github.com/just-the-docs/just-the-docs) for the documentation theme. |
32 | 125 |
|
33 | 126 | ## Contributing |
34 | 127 |
|
35 | 128 | We welcome contributions! Please see our [Contributing Guide](https://github.com/Stillpoint-Software/.github/blob/main/.github/CONTRIBUTING.md) |
36 | | -for more details. |
| 129 | +for more detai |
0 commit comments