Skip to content

Commit 0a92fcd

Browse files
committed
Update documentation and samples and change project to minimum version of 4.5.2
1 parent 27f47b6 commit 0a92fcd

9 files changed

Lines changed: 142 additions & 207 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*.user
77
*.userosscache
88
*.sln.docstates
9+
*.bak
910

1011
# User-specific files (MonoDevelop/Xamarin Studio)
1112
*.userprefs

README.md

Lines changed: 103 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,37 @@
11
# Westwind CSharp Scripting
22
### Dynamically compile and execute CSharp code at runtime
33

4-
This small `CSharpScripting` class provides an easy way to compile and execute C# on the fly at runtime using the .NET compiler services. This is ideal to provide support for addin's and application automation tasks that are user configurable.
4+
<small>for .NET 4.52 and later</small>
5+
6+
The small `CSharpScripting` class provides an easy way to compile and execute C# on the fly from source code at runtime using the .NET compiler services on full Framework .NET. You can use Roslyn compilation for the latest C# features, or classic C# 5 features.
7+
8+
This class makes is very easy to integrate simple scripting or text merging features into applications with minimal effort.
9+
10+
This library provides:
11+
12+
**Execution Features**
13+
14+
* `ExecuteCode()` - Execute an arbitrary block of code
15+
* `Evaluate()` - Evaluate an expression from a code string
16+
* `ExecuteMethod()` - Execute one or more methods from source
17+
* `CompileClass()` - Generate a class instance from C# code
18+
19+
**Support features**
20+
21+
* Assembly Caching so not every execution generates a new assembly
22+
* Ability to compile entire classes and execute them
23+
* Automatic Assembly Cleanup at shutdown
24+
* Use Roslyn or Classic C# compiler interchangably
25+
* Display errors and source and line numbers
526

6-
The library supports both the latest Roslyn compiler and classic CSharp compilation.
727

828
> #### Requires Roslyn Code Providers for your Project
9-
> If you want to use Roslyn compilation you have to make sure you add the `Microsoft.CodeDom.CompilerServices` NuGet Package to your project to provide the required compiler binaries for your application. This should be added to the application's start project.
29+
> If you want to use Roslyn compilation for the latest C# features you have to make sure you add the `Microsoft.CodeDom.CompilerServices` NuGet Package to your application's root project to provide the required compiler binaries for your application.
1030
>
11-
> Note that this adds a sizable chunk of files to your application's output folder in the `roslyn` folder. If you don't want this you can use the classic compiler, at the cost of not having access to C# 6+ features.
31+
> Note that this adds a sizable chunk of files to your application's output folder in the `\roslyn` folder. If you don't want this you can use the classic compiler, at the cost of not having access to C# 6+ features.
1232
1333
## Usage
14-
Using the `CSharpScriptExecution` class is very easy. It works by letting you provide either a simple code snippet that can optionally `return` a value, or a complete method signature with a method header and return statement. You can also provide multiple method that can be called explicitly using the `InvokeMethod()` operation.
34+
Using the `CSharpScriptExecution` class is very easy. It works with code passed as strings for either a Code block, expression, one or more methods or even as a full C# class that can be turned into an instance.
1535

1636
You can add **Assembly References** and **Namespaces** via the `AddReferece()` and `AddNamespace()` methods.
1737

@@ -59,7 +79,9 @@ Assert.IsFalse(script.Error, script.ErrorMessage);
5979
Assert.IsTrue(result.Contains(" = 30"));
6080
```
6181

62-
Note that the `return` in your code snippet is optional - you can just run code without a result value. Any parameters you pass in can be accessed either via `parameters[0]`, `parameters[1]` etc. or using a simpler string representation of `@0`, `@1`.
82+
Note that the `return` in your code snippet is optional - you can just run code without a result value.
83+
84+
> Any parameters you pass in can be accessed either via `parameters[0]`, `parameters[1]` etc. or using a simpler string representation of `@0`, `@1`.
6385
6486
### Evaluating an expression
6587
If you want to evaluate a single expression, there's a shortcut `Evalute()` method that works pretty much the same:
@@ -86,10 +108,10 @@ Assert.IsFalse(script.Error, script.ErrorMessage);
86108
Assert.IsTrue(result is decimal, script.ErrorMessage);
87109
```
88110

89-
This method is a shortcut wrapper and simply wraps your code into a single line `return {exp};` statement.
111+
This method is a shortcut wrapper and simply wraps your code into a single line `return {exp};` statement.
90112

91113
### Executing a Method
92-
Another way to execute code is to provide a full method body which is a little more explicit and makes it easier to reference parameters passed in.
114+
`ExecuteCode()` and `Evaluate()` are shortcuts for the slightly lower level and more flexible `ExecuteMethod()` method which as the name implies allows you to specify a single or multiple methods. In fact you can provide an **entire class body** including properties, events and nested class definitions in the code passed in. This gives a lot of flexibility as you can properly type parameters and return types:
93115

94116
```csharp
95117
var script = new CSharpScriptExecution()
@@ -165,4 +187,76 @@ result = instance.GoodbyeWorld();
165187

166188
Console.WriteLine($"Result: {result}");
167189
Assert.IsTrue(result.Contains("Goodbye Markus"));
168-
```
190+
```
191+
192+
### Compiling and Executing a Class
193+
You can also compile an **entire class** and then get passed back a `dynamic` reference to that class so that you can explicitly use that object:
194+
195+
196+
```cs
197+
var script = new CSharpScriptExecution()
198+
{
199+
SaveGeneratedCode = true,
200+
CompilerMode = ScriptCompilerModes.Roslyn
201+
};
202+
script.AddDefaultReferencesAndNamespaces();
203+
204+
var code = $@"
205+
using System;
206+
207+
namespace MyApp
208+
{{
209+
public class Math
210+
{{
211+
public string Add(int num1, int num2)
212+
{{
213+
// string templates
214+
var result = num1 + "" + "" + num2 + "" = "" + (num1 + num2);
215+
Console.WriteLine(result);
216+
217+
return result;
218+
}}
219+
220+
public string Multiply(int num1, int num2)
221+
{{
222+
// string templates
223+
var result = $""{{num1}} * {{num2}} = {{(num1 * num2)}}"";
224+
Console.WriteLine(result);
225+
226+
return result;
227+
}}
228+
229+
}}
230+
}}
231+
";
232+
233+
dynamic math = script.CompileClass(code);
234+
235+
Console.WriteLine(script.GeneratedClassCodeWithLineNumbers);
236+
237+
Assert.IsFalse(script.Error,script.ErrorMessage);
238+
Assert.IsNotNull(math);
239+
240+
string addResult = math.Add(10, 20);
241+
string multiResult = math.Multiply(3 , 7);
242+
243+
244+
Assert.IsTrue(addResult.Contains(" = 30"));
245+
Assert.IsTrue(multiResult.Contains(" = 21"));
246+
```
247+
248+
249+
## Usage Notes
250+
251+
252+
253+
## License
254+
This library is published under **MIT license** terms.
255+
256+
**Copyright &copy; 2012-2019 Rick Strahl, West Wind Technologies**
257+
258+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
259+
260+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
261+
262+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md.saved.bak

Lines changed: 0 additions & 170 deletions
This file was deleted.

Westwind.Scripting.Test/App.config

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<?xml version="1.0" encoding="utf-8" ?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<configuration>
33
<appSettings>
4-
<add key="aspnet:RoslynCompilerLocation" value="roslyn" />
4+
<add key="aspnet:RoslynCompilerLocation" value="roslyn"/>
55
</appSettings>
6-
</configuration>
6+
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup></configuration>

0 commit comments

Comments
 (0)