Expressions¶
Static factory classes that produce ExpressionRef instances for common .NET code patterns.
See also: TypeRef & Primitives | Types | LanguageExt Expressions
Overview¶
Expression factories pair with typed wrappers to form the second layer of the type system. Where TaskTypeRef represents the type Task<T>, TaskExpression produces code like Task.CompletedTask or Task.FromResult(value).
using Deepstaging.Roslyn.Expressions;
// Produce expression code without string assembly
TaskExpression.CompletedTask // → "global::System.Threading.Tasks.Task.CompletedTask"
TaskExpression.FromResult("42") // → "global::System.Threading.Tasks.Task.FromResult(42)"
EqualityComparerExpression.DefaultEquals("string", "_name", "value")
// → "global::System.Collections.Generic.EqualityComparer<string>.Default.Equals(_name, value)"
TaskExpression¶
Async task patterns from System.Threading.Tasks.
| Method | Produces |
|---|---|
CompletedTask |
Task.CompletedTask |
CompletedValueTask |
ValueTask.CompletedTask |
FromResult(value) |
Task.FromResult(value) |
FromResult(type, value) |
Task.FromResult<T>(value) |
Run(expr) |
Task.Run(expr) |
Delay(delay) |
Task.Delay(delay) |
WhenAll(tasks...) |
Task.WhenAll(t1, t2, ...) |
WhenAny(tasks...) |
Task.WhenAny(t1, t2, ...) |
// Fallback for nullable delegate
TypeRef.From("OnSave").Invoke("entity")
.OrDefault(TaskExpression.CompletedTask)
.Await()
// → "await OnSave?.Invoke(entity) ?? global::System.Threading.Tasks.Task.CompletedTask"
// Wrap a synchronous value
TaskExpression.FromResult("count")
// → "global::System.Threading.Tasks.Task.FromResult(count)"
EqualityComparerExpression¶
Equality comparison via EqualityComparer<T>.Default.
| Method | Produces |
|---|---|
Default(type) |
EqualityComparer<T>.Default |
DefaultEquals(type, left, right) |
EqualityComparer<T>.Default.Equals(left, right) |
DefaultGetHashCode(type, value) |
EqualityComparer<T>.Default.GetHashCode(value) |
EqualityComparerExpression.DefaultEquals("string", "_name", "value")
// → "global::System.Collections.Generic.EqualityComparer<string>.Default.Equals(_name, value)"
EqualityComparerExpression.DefaultGetHashCode("int", "_id")
// → "global::System.Collections.Generic.EqualityComparer<int>.Default.GetHashCode(_id)"
CollectionExpression¶
Constructor expressions for List<T>, Dictionary<K,V>, and HashSet<T>.
| Method | Produces |
|---|---|
NewList(elementType) |
new List<T>() |
NewList(elementType, capacity) |
new List<T>(capacity) |
NewDictionary(keyType, valueType) |
new Dictionary<K, V>() |
NewDictionary(keyType, valueType, capacity) |
new Dictionary<K, V>(capacity) |
NewHashSet(elementType) |
new HashSet<T>() |
NewHashSet(elementType, comparer) |
new HashSet<T>(comparer) |
EmptyEnumerable(elementType) |
Enumerable.Empty<T>() |
EmptyArray(elementType) |
Array.Empty<T>() |
CollectionExpression.NewList("Order")
// → "new global::System.Collections.Generic.List<Order>()"
CollectionExpression.EmptyEnumerable("string")
// → "global::System.Linq.Enumerable.Empty<string>()"
CollectionExpression.EmptyArray("int")
// → "global::System.Array.Empty<int>()"
NullableExpression¶
Member access patterns for Nullable<T>.
| Method | Produces |
|---|---|
HasValue(expr) |
expr.HasValue |
Value(expr) |
expr.Value |
GetValueOrDefault(expr) |
expr.GetValueOrDefault() |
GetValueOrDefault(expr, default) |
expr.GetValueOrDefault(default) |
NullableExpression.HasValue("age") // → "age.HasValue"
NullableExpression.GetValueOrDefault("score", "0") // → "score.GetValueOrDefault(0)"
PropertyChangedExpression¶
INotifyPropertyChanged event patterns.
| Method | Produces |
|---|---|
NewEventArgs(name) |
new PropertyChangedEventArgs("Name") |
NewChangingEventArgs(name) |
new PropertyChangingEventArgs("Name") |
Raise(handler, sender, args) |
handler?.Invoke(sender, args) |
PropertyChangedExpression.NewEventArgs("Name")
// → "new global::System.ComponentModel.PropertyChangedEventArgs(\"Name\")"
PropertyChangedExpression.Raise("PropertyChanged", "this", "e")
// → "PropertyChanged?.Invoke(this, e)"
LazyExpression¶
Lazy<T> construction and access.
| Method | Produces |
|---|---|
New(type, factory) |
new Lazy<T>(factory) |
New(type, factory, isThreadSafe) |
new Lazy<T>(factory, isThreadSafe) |
Value(expr) |
expr.Value |
IsValueCreated(expr) |
expr.IsValueCreated |
LazyExpression.New("ExpensiveService", "() => new ExpensiveService()")
// → "new global::System.Lazy<ExpensiveService>(() => new ExpensiveService())"
LazyExpression.Value("_lazyService") // → "_lazyService.Value"
DisposableExpression¶
Dispose patterns for IDisposable and IAsyncDisposable.
| Method | Produces |
|---|---|
Dispose(expr) |
expr.Dispose() |
ConditionalDispose(expr) |
expr?.Dispose() |
DisposeAsync(expr) |
await expr.DisposeAsync() |
DisposeAsyncCall(expr) |
expr.DisposeAsync() (without await) |
ConditionalDisposeAsync(expr) |
if (expr != null) await expr.DisposeAsync() |
DisposableExpression.Dispose("_connection")
// → "_connection.Dispose()"
DisposableExpression.DisposeAsync("_stream")
// → "await _stream.DisposeAsync()"
ComparerExpression¶
Ordering comparison via Comparer<T>.Default.
| Method | Produces |
|---|---|
Default(type) |
Comparer<T>.Default |
DefaultCompare(type, left, right) |
Comparer<T>.Default.Compare(left, right) |
ComparerExpression.DefaultCompare("int", "_priority", "other._priority")
// → "global::System.Collections.Generic.Comparer<int>.Default.Compare(_priority, other._priority)"
ImmutableCollectionExpression¶
Factory methods for immutable collections.
| Method | Produces |
|---|---|
EmptyArray(type) |
ImmutableArray<T>.Empty |
CreateArray(type, items...) |
ImmutableArray.Create<T>(items) |
EmptyDictionary(keyType, valueType) |
ImmutableDictionary<K, V>.Empty |
CreateDictionaryBuilder(keyType, valueType) |
ImmutableDictionary.CreateBuilder<K, V>() |
EmptyList(elementType) |
ImmutableList<T>.Empty |
CreateList(elementType, items...) |
ImmutableList.Create<T>(items) |
ImmutableCollectionExpression.EmptyArray("string")
// → "global::System.Collections.Immutable.ImmutableArray<string>.Empty"
ImmutableCollectionExpression.CreateArray("int", "1", "2", "3")
// → "global::System.Collections.Immutable.ImmutableArray.Create<int>(1, 2, 3)"
ImmutableCollectionExpression.EmptyList("Order")
// → "global::System.Collections.Immutable.ImmutableList<Order>.Empty"
JsonExpression¶
Serialization patterns for System.Text.Json.JsonSerializer.
| Method | Produces |
|---|---|
Serialize(value) |
JsonSerializer.Serialize(value) |
Serialize(value, options) |
JsonSerializer.Serialize(value, options) |
Deserialize(type, json) |
JsonSerializer.Deserialize<T>(json) |
Deserialize(type, json, options) |
JsonSerializer.Deserialize<T>(json, options) |
JsonExpression.Serialize("entity")
// → "global::System.Text.Json.JsonSerializer.Serialize(entity)"
JsonExpression.Deserialize("Customer", "json")
// → "global::System.Text.Json.JsonSerializer.Deserialize<Customer>(json)"
HttpExpression¶
HTTP verb constants and async request patterns.
| Method | Produces |
|---|---|
Get |
HttpMethod.Get |
Post |
HttpMethod.Post |
Put |
HttpMethod.Put |
Patch |
HttpMethod.Patch |
Delete |
HttpMethod.Delete |
Verb(name) |
HttpMethod.{name} |
GetAsync(client, url) |
client.GetAsync(url) |
PostAsync(client, url, content) |
client.PostAsync(url, content) |
PutAsync(client, url, content) |
client.PutAsync(url, content) |
DeleteAsync(client, url) |
client.DeleteAsync(url) |
SendAsync(client, request) |
client.SendAsync(request) |
SendAsync(client, request, ct) |
client.SendAsync(request, ct) |
EnsureSuccessStatusCode(response) |
response.EnsureSuccessStatusCode() |
ReadAsStringAsync(response) |
response.Content.ReadAsStringAsync() |
HttpExpression.GetAsync("_client", "url")
// → "_client.GetAsync(url)"
HttpExpression.EnsureSuccessStatusCode("response")
// → "response.EnsureSuccessStatusCode()"
EntityFrameworkExpression¶
EF Core CRUD patterns.
| Method | Produces |
|---|---|
Set(context, entityType) |
context.Set<T>() |
SaveChangesAsync(context) |
context.SaveChangesAsync() |
SaveChangesAsync(context, ct) |
context.SaveChangesAsync(ct) |
FindAsync(dbSet, keys...) |
dbSet.FindAsync(keys) |
AddAsync(dbSet, entity) |
dbSet.AddAsync(entity) |
Remove(dbSet, entity) |
dbSet.Remove(entity) |
EntityFrameworkExpression.Set("_context", "Customer")
// → "_context.Set<Customer>()"
EntityFrameworkExpression.SaveChangesAsync("_context", "cancellationToken")
// → "_context.SaveChangesAsync(cancellationToken)"
DependencyInjectionExpression¶
Service registration and resolution patterns.
| Method | Produces |
|---|---|
AddSingleton(services, service, impl) |
services.AddSingleton<TService, TImpl>() |
AddSingleton(services, service) |
services.AddSingleton<TService>() |
AddScoped(services, service, impl) |
services.AddScoped<TService, TImpl>() |
AddScoped(services, service) |
services.AddScoped<TService>() |
AddTransient(services, service, impl) |
services.AddTransient<TService, TImpl>() |
AddTransient(services, service) |
services.AddTransient<TService>() |
GetRequiredService(provider, type) |
provider.GetRequiredService<T>() |
GetService(provider, type) |
provider.GetService<T>() |
DependencyInjectionExpression.AddScoped("services", "IOrderService", "OrderService")
// → "services.AddScoped<IOrderService, OrderService>()"
DependencyInjectionExpression.GetRequiredService("provider", "IOrderService")
// → "provider.GetRequiredService<IOrderService>()"
LoggingExpression¶
Structured logging method calls.
| Method | Produces |
|---|---|
LogTrace(logger, args...) |
logger.LogTrace(args) |
LogDebug(logger, args...) |
logger.LogDebug(args) |
LogInformation(logger, args...) |
logger.LogInformation(args) |
LogWarning(logger, args...) |
logger.LogWarning(args) |
LogError(logger, args...) |
logger.LogError(args) |
LogCritical(logger, args...) |
logger.LogCritical(args) |
LoggingExpression.LogInformation("_logger", "\"Processing order {OrderId}\"", "order.Id")
// → "_logger.LogInformation(\"Processing order {OrderId}\", order.Id)"
ConfigurationExpression¶
Configuration access patterns.
| Method | Produces |
|---|---|
GetSection(config, key) |
config.GetSection(key) |
GetValue(config, type, key) |
config.GetValue<T>(key) |
GetConnectionString(config, name) |
config.GetConnectionString(name) |
Bind(config, key, instance) |
config.GetSection(key).Bind(instance) |
ConfigurationExpression.GetValue("_config", "int", "\"MaxRetries\"")
// → "_config.GetValue<int>(\"MaxRetries\")"
ConfigurationExpression.GetConnectionString("_config", "\"Default\"")
// → "_config.GetConnectionString(\"Default\")"
DiagnosticsExpression¶
OpenTelemetry / System.Diagnostics patterns.
| Method | Produces |
|---|---|
StartActivity(source, name) |
source.StartActivity(name) |
StartActivity(source, name, kind) |
source.StartActivity(name, kind) |
SetTag(activity, key, value) |
activity.SetTag(key, value) |
SetStatus(activity, statusCode) |
activity.SetStatus(statusCode) |
StartNew() |
Stopwatch.StartNew() |
Assert(condition) |
Debug.Assert(condition) |
Assert(condition, message) |
Debug.Assert(condition, message) |
DiagnosticsExpression.StartNew()
// → "global::System.Diagnostics.Stopwatch.StartNew()"
DiagnosticsExpression.SetTag("activity", "\"user.id\"", "userId")
// → "activity.SetTag(\"user.id\", userId)"
HostingExpression¶
Hosted service registration patterns for Microsoft.Extensions.Hosting.
| Method | Produces |
|---|---|
AddHostedService(services, type) |
services.AddHostedService<T>() |
AddHostedServiceFromProvider(services, type) |
services.AddHostedService(sp => sp.GetRequiredService<T>()) |
HostingExpression.AddHostedService("services", "MyWorker")
// → "services.AddHostedService<MyWorker>()"
HostingExpression.AddHostedServiceFromProvider("services", "MyWorker")
// → "services.AddHostedService(sp => sp.GetRequiredService<MyWorker>())"
ExceptionExpression¶
Exception throwing and guard clause patterns.
| Method | Produces |
|---|---|
New(exceptionType, args...) |
new ExceptionType(args) |
ThrowNew(exceptionType, args...) |
throw new ExceptionType(args) |
ThrowIfNull(param) |
ArgumentNullException.ThrowIfNull(param) |
ThrowIfNullOrEmpty(param) |
ArgumentException.ThrowIfNullOrEmpty(param) |
ThrowIfNullOrWhiteSpace(param) |
ArgumentException.ThrowIfNullOrWhiteSpace(param) |
ThrowIfNegative(param) |
ArgumentOutOfRangeException.ThrowIfNegative(param) |
ThrowIfZero(param) |
ArgumentOutOfRangeException.ThrowIfZero(param) |
ThrowIfDisposed(condition, instance) |
ObjectDisposedException.ThrowIf(condition, instance) |
ExceptionExpression.ThrowNew(ExceptionTypes.ArgumentNull, "nameof(value)")
// → "throw new global::System.ArgumentNullException(nameof(value))"
ExceptionExpression.ThrowIfNull("value")
// → "global::System.ArgumentNullException.ThrowIfNull(value)"
ExceptionExpression.New(ExceptionTypes.InvalidOperation, "\"Item not found\"")
// → "new global::System.InvalidOperationException(\"Item not found\")"
Uses ExceptionTypes constants from the Types page.
LinqExpression¶
LINQ query-syntax expression builder (from … select). Returns an ExpressionRef suitable for expression bodies, return statements, or assignments.
| Method | Description |
|---|---|
From(variable, source) |
Start a query with from x in source |
.ThenFrom(variable, source) |
Add another from clause (cross join / SelectMany) |
.Let(variable, expression) |
Add a let clause |
.Where(condition) |
Add a where filter |
.OrderBy(key) |
Add an orderby clause |
.OrderByDescending(key) |
Add an orderby … descending clause |
.Join(variable, source, left, right) |
Add a join … on … equals clause |
.Join(variable, source, left, right, into) |
Add a join … into group join clause |
.GroupBy(element, key) |
Terminate with group … by (returns ExpressionRef) |
.GroupBy(element, key, into) |
Add group … by … into with continuation |
.Select(expression) |
Terminate with select (returns ExpressionRef) |
// Simple select
LinqExpression
.From("x", "source")
.Select("x.Name")
// Where + OrderBy + Select
LinqExpression
.From("x", "source")
.Where("x.IsActive")
.OrderBy("x.Name")
.Select("x")
// Nested from (SelectMany)
LinqExpression
.From("customer", "customers")
.ThenFrom("order", "customer.Orders")
.Where("order.Total > 100")
.Select("new { customer.Name, order.Id }")
// Group by with into continuation
LinqExpression
.From("x", "source")
.GroupBy("x", "x.Category", into: "g")
.ThenFrom("item", "g")
.Select("new { Group = g.Key, Item = item.Name }")
Builder Extensions¶
Expression factories also include builder extensions that wire common patterns into TypeBuilder and PropertyBuilder.
WithNotifyingSetter¶
Configures a property setter with equality guard and INotifyPropertyChanged notification.
using Deepstaging.Roslyn.Expressions;
using Deepstaging.Roslyn.Emit.Interfaces.Observable;
var type = TypeBuilder.Class("ViewModel")
.ImplementsINotifyPropertyChanged()
.AddProperty("Name", "string", p => p
.WithNotifyingSetter("_name", alsoNotify: ["FullName"]));
Generates:
public string Name
{
get => _name;
set
{
if (EqualityComparer<string>.Default.Equals(_name, value)) return;
_name = value;
OnPropertyChanged(nameof(Name));
OnPropertyChanged(nameof(FullName));
}
}
| Parameter | Type | Description |
|---|---|---|
fieldName |
string |
The backing field name |
onPropertyChangedMethod |
string |
Method to call (default: "OnPropertyChanged") |
alsoNotify |
params string[] |
Additional properties to notify |
WithLazyField¶
Adds a Lazy<T> backing field and read-only property exposing .Value.
var type = TypeBuilder.Class("Service")
.WithLazyField(
TypeRef.From("ExpensiveService"),
"_lazyService",
ExpressionRef.From("() => new ExpensiveService()"),
"Service");
Generates:
private readonly Lazy<ExpensiveService> _lazyService =
new Lazy<ExpensiveService>(() => new ExpensiveService());
public ExpensiveService Service => _lazyService.Value;
| Parameter | Type | Description |
|---|---|---|
valueType |
TypeRef |
The lazily-initialized type |
fieldName |
string |
The backing field name |
factory |
ExpressionRef |
The factory expression |
propertyName |
string |
The public property name |