Inject
InjectExpression resolves a service from an IServiceProvider at runtime. It is the expression tree equivalent of constructor injection or IServiceProvider.GetRequiredService<T>().
At compile time the expression tree captures the service type. At runtime the service provider is injected by calling Compile(serviceProvider) on the lambda, which replaces all InjectExpression nodes with their resolved values before compilation.
Factory Methods
using static Hyperbee.Expressions.ExpressionExtensions;
| Overload | Description |
|---|---|
Inject( Type type, IServiceProvider sp, string key = null, Expression defaultValue = null ) | Resolve by type with provider |
Inject( Type type, string key = null, Expression defaultValue = null ) | Resolve by type – provider supplied at compile time |
Inject<T>( IServiceProvider sp, string key = null, Expression defaultValue = null ) | Generic resolve with provider |
Inject<T>( string key = null, Expression defaultValue = null ) | Generic resolve – provider supplied at compile time |
Usage
Inject at Compile Time
The idiomatic pattern is to supply the IServiceProvider when compiling, not when building the tree. This allows the tree to be built once and compiled with different containers.
using static System.Linq.Expressions.Expression;
using static Hyperbee.Expressions.ExpressionExtensions;
// Build the tree (no IServiceProvider yet)
var injected = Inject<IMyService>();
var expr = Block(
Call( injected, typeof(IMyService).GetMethod("Execute")! )
);
var lambda = Lambda<Action>( expr );
// Compile with the service provider -- Inject nodes are resolved here
var fn = lambda.Compile( serviceProvider );
fn();
Inject with a Named Key
// Keyed services (requires .NET 8 / IKeyedServiceProvider)
var service = Inject<IMyService>( key: "primary" );
Inject with a Default Value
// Falls back to defaultValue if the service is not registered
var service = Inject<IMyService>(
defaultValue: Constant( new NoopMyService() )
);
Inject by Type
var service = Inject( typeof(IMyService) );
Compiling with a Service Provider
// Extension method on LambdaExpression
public static TResult Compile<TResult>(
this Expression<TResult> expression,
IServiceProvider serviceProvider,
bool preferInterpretation = false )
var fn = lambda.Compile( serviceProvider );
This walks the expression tree, finds all IDependencyInjectionExpression nodes (including InjectExpression and ConfigurationExpression), sets the provider on each, then compiles the result.
Notes
InjectExpressionimplementsIDependencyInjectionExpression, which is the marker interface used byCompile(serviceProvider)to find all nodes that need a provider.- If no
IServiceProvideris set and nodefaultValueis provided, accessing the service at runtime throwsInvalidOperationException. - See Configuration Value for
IConfigurationaccess. - See Dependency Injection for the full DI compilation pattern.