EmitToolbox 0.3.0-dev11120158
EmitToolbox
Using System.Reflection.Emit to dynamically create types and methods at runtime is prone to errors and
can be quite complex.
To effectively emit dynamic IL code,
one must have a deep understanding of the Common Intermediate Language (CIL) and the .NET runtime.
The EmitToolbox library aims to simplify this process by providing a set of high-level abstractions and utilities.
Concepts
- 'DynamicAssembly': Builder for defining dynamic assemblies. It can define classes and structs.
- 'DynamicType': Builder for defining dynamic types. Use it to create
DynamicMethod,DynamicFieldandDynamicPropertyinstances. - 'DynamicMethod': Builder for defining the code of dynamic methods. This framework provides extensions methods to
- 'DynamicField': Builder for defining dynamic fields.
- 'DynamicProperty': Builder for defining dynamic properties and corresponding setters and getters.
Usage
Create a Dynamic Assembly
Use the following code to create an executable dynamic assembly:
var assembly = DynamicAssembly.DefineExecutable("SampleAssembly");
Or you can create an assembly that can be exported to a file but cannot be executed directly:
var assembly = DynamicAssembly.DefineExportable("SampleAssembly");
// ...
assemly.Export("./MyDynamicAssembly.dll");
Basic Example
using EmitToolbox.Framework;
using EmitToolbox.Framework.Extensions;
using EmitToolbox.Framework.Symbols;
var assembly = DynamicAssembly.DefineExecutable("SampleAssembly");
var type = assembly.DefineClass("SampleClass");
// Define an instance field named 'Backing' of type 'int'
var backingField = type.FieldFactory.DefineInstance(typeof(int), "Backing");
// Define an instance property named 'Value' of type 'int'
var valueProperty = type.PropertyFactory.DefineInstance<int>("Value");
// Define and bind getter accessor for the property
var getter = type.MethodFactory.Instance.DefineFunctor<int>(
"get_Value", [], hasSpecialName: true);
// Get the 'this' instance symbol.
// This symbol is used to access the instance field in the method body.
var thisSymbol = getter.This();
// Convert the dynamic field into a symbol than can be used in the method building context
// by binding it to the 'getter' method and 'this' instance.
var fieldSymbol = backingField.SymbolOf<int>(getter, thisSymbol);
// Return the value of the field + 1.
// Here, extension operator '+' for 'ISymbol<int>' is used.
// Use the namespace 'EmitToolbox.Framework.Extensions' to access these extension methods.
// 'getter.Value(1)' is to create a literal symbol that represents the value 1.
getter.Return(fieldSymbol + getter.Value(1));
// Bind the 'getter' method as the getter accessor of this property.
valueProperty.BindGetter(getter);
// After building this type, the type and its methods, fields, and properties can be used.
type.Build();
// Following example is about to use this type throw reflection.
// Usually, the built types implement interfaces, and they should be used as interfaces for better performance.
// This part is only for demonstration purpose.
// Instantiate an instance of the built type.
var instance = Activator.CreateInstance(type.BuildingType)!;
// Create a functor from the getter accessor of the property.
var functor = valueProperty.Getter!.BuildingMethod.CreateDelegate<Func<int>>(testInstance);
// Using reflection to set the value of the backing field to 1.
backingField.BuildingField.SetValue(instance, 1);
// Then invoke the functor, the result should be 3.
var result = functor(2);
Showing the top 20 packages that depend on EmitToolbox.
| Packages | Downloads |
|---|---|
|
InjectionExpert
A dependency injection library based on dynamic IL weaving.
|
5 |
|
SnapshotExpert
A library for automatic BSON/JSON snapshot serailization, with built-in support for reference tracking.
|
5 |
|
SnapshotExpert
A library for automatic BSON/JSON snapshot serailization, with built-in support for reference tracking.
|
4 |
|
InjectionExpert
A dependency injection library based on dynamic IL weaving.
|
3 |
|
InjectionExpert
A dependency injection library based on dynamic IL weaving.
|
2 |
|
InjectionExpert
A dependency injection library based on dynamic IL generation. It supports constructor injection and member injection.
|
2 |
|
SnapshotExpert
A library for automatic BSON/JSON snapshot serailization, with built-in support for reference tracking.
|
2 |
|
SnapshotExpert.Proxying
This package provides extensions for SnapshotExpert to serialize and deserialize calls. It provides generators for call-proxies which serialize calls, and call-handlers which deserialize calls and redirect it to the proxied method. This pacakge also includes serializers for CancellationToken, Task<T>, ValueTask<T>, etc.
|
2 |
|
InjectionExpert
A dependency injection library based on dynamic IL weaving.
|
1 |
[Version 0.3.0]
This version introduces a new framework which is not compatible to previous version. It relies more on interfaces rather than abstract classes to describe symbols.
Meanwhile, we realized that only providing support at a high abstraction level is not enough (generic symbols and methods), even though it significantly reduces the risk of wrong usage. Therefore, this framework has more support for low-level constructs:
- Most symbols and methods now support non-generic symbols.
- Infrastructures of 'System.Runtime.Emit' (e.g., 'TypeBuilder', 'MethodBuilder') are now publicly accessible.
Breaking Changes:
- '...BuildingContext' classes are now renamed as 'Dynamic...'.
- 'ValueType' of symbols are now renamed to 'ContentType'; it now represents the actual type of that a symbol holds, thus, it can be a reference type.
Problem Fixes:
- Code for loading/storing references is now fixed.
- Now overriding methods with 'out' parameters no longer causes exceptions to signature mismatching.
.NET 9.0
- JetBrains.Annotations (>= 2025.2.2)