TCIS.Pluggable.Engine.Autofac
1.0.0-rc.19
dotnet add package TCIS.Pluggable.Engine.Autofac --version 1.0.0-rc.19
NuGet\Install-Package TCIS.Pluggable.Engine.Autofac -Version 1.0.0-rc.19
<PackageReference Include="TCIS.Pluggable.Engine.Autofac" Version="1.0.0-rc.19" />
<PackageVersion Include="TCIS.Pluggable.Engine.Autofac" Version="1.0.0-rc.19" />
<PackageReference Include="TCIS.Pluggable.Engine.Autofac" />
paket add TCIS.Pluggable.Engine.Autofac --version 1.0.0-rc.19
#r "nuget: TCIS.Pluggable.Engine.Autofac, 1.0.0-rc.19"
#:package TCIS.Pluggable.Engine.Autofac@1.0.0-rc.19
#addin nuget:?package=TCIS.Pluggable.Engine.Autofac&version=1.0.0-rc.19&prerelease
#tool nuget:?package=TCIS.Pluggable.Engine.Autofac&version=1.0.0-rc.19&prerelease
TCIS.Pluggable.Engine.Autofac
Swaps the default DI container for Autofac and adds AOP logging to the Pluggable Engine: input arguments, execution time and exceptions are logged for boundary classes without a single logging statement in the business code.
Required for Template 3 (Pluggable). Optional — but recommended — for Templates 1 and 2.
Table of contents
| Section | Contents |
|---|---|
| 1 | Registration |
| 2 | What gets intercepted |
| 3 | Configuration |
| 4 | ⚠️ The configuration binding trap |
| 5 | Pitfalls |
1. Registration
dotnet add package TCIS.Pluggable.Engine.Autofac
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseTPluggableAutofac();
// or with explicit settings
builder.Host.UseTPluggableAutofac(
configSection: "TLogSettings:AopSettings",
configureOptions: o => o.TargetNamespaces.Add("Port.CatLai"));
One call does three things:
| # | Work |
|---|---|
| 1 | Replaces the DI container with Autofac (AutofacServiceProviderFactory) |
| 2 | Registers PluggableLoggingModule, which injects interceptors |
| 3 | Replaces IRealTypeResolver with AutofacRealTypeResolver so the engine sees through proxies to the real type |
Step 3 matters more than it looks: without it, discovery and metrics would report the proxy type name instead of your class, and step resolution by type would miss.
2. What gets intercepted
PluggableLoggingModule decides in four steps:
| # | Rule |
|---|---|
| 1 | Early exclusion — namespace not in TargetNamespaces, or the name ends with an ExcludedSuffixes entry |
| 2 | By interface — implements IPipelineStep<> or IBusinessRule<> → always intercepted |
| 3 | By naming convention — the name ends with an IncludedSuffixes entry |
| 4 | Interception is attached through an Autofac 6 pipeline middleware at the Activation phase |
Rule 2 is the important one: every pipeline step and business rule is instrumented regardless of its name, because those are exactly the classes whose duration and failures the metrics are built on.
// Intercepted — implements IPipelineStep<>
[PlatformStep("Gate.ValidateContainer", executionOrder: 10)]
public sealed class CoreValidateContainerStep : IPipelineStep<IGateInContext> { … }
// Intercepted — name ends with "Service"
public sealed class BerthAllocationService : IBerthAllocationService { … }
// NOT intercepted — name ends with "Context"
public sealed class GateInContext : TPipelineContextBase<GateInResponse> { … }
3. Configuration
{
"TLogSettings": {
"AopSettings": {
"TargetNamespaces": [ "TCIS" ],
"ExcludedSuffixes": [ "Context", "Options", "Attribute" ],
"IncludedSuffixes": [ "Service", "QueryProvider" ]
}
}
}
| Option | Default | Purpose |
|---|---|---|
TargetNamespaces |
["TCIS"] |
Root namespaces considered at all. Anything outside is ignored immediately |
ExcludedSuffixes |
["Context", "Options", "Attribute"] |
Never intercept — avoids proxy overhead on configuration and context objects |
IncludedSuffixes |
["Service", "QueryProvider"] |
Boundary classes to intercept by naming convention |
4. ⚠️ The configuration binding trap
IConfiguration.Bind appends to a list that already holds defaults; it does not replace it.
{ "TLogSettings": { "AopSettings": { "TargetNamespaces": [ "Port.CatLai" ] } } }
// What you expect
["Port.CatLai"]
// What you actually get
["TCIS", "Port.CatLai"]
This surprises people in both directions: a namespace you meant to exclude stays included, and a list you meant to shrink grows instead. To end up with only your own value, clear the list in code:
builder.Host.UseTPluggableAutofac(configureOptions: o =>
{
o.TargetNamespaces.Clear();
o.TargetNamespaces.Add("Port.CatLai");
});
configureOptions runs after binding, so it always has the last word.
This behaviour is pinned by R4_AopOptionsBindingTests — it is a property of Microsoft.Extensions.Configuration, not something this package can change.
5. Pitfalls
| # | Pitfall | Consequence |
|---|---|---|
| 1 | Expecting Bind to replace a list |
Defaults silently remain — see section 4 |
| 2 | Adding an interception target whose class is sealed with no interface |
Autofac cannot build a proxy |
| 3 | Registering services before UseTPluggableAutofac in a way that bypasses the container factory |
Those registrations are not intercepted |
| 4 | Intercepting hot paths by adding a broad suffix such as "Entity" |
Proxy overhead on objects created thousands of times per request |
| 5 | Assuming interception implies transaction or retry behaviour | It only logs — it changes no semantics |
Captive dependencies are avoided by design: the interceptor is
ResolveNamed-ed inside the middleware, once per resolution, rather than being held at module scope. Do not "optimise" that by caching the interceptor — it would capture a scoped graph into a singleton.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Autofac (>= 8.1.1)
- Autofac.Extensions.DependencyInjection (>= 10.0.0)
- Autofac.Extras.DynamicProxy (>= 7.1.0)
- Castle.Core.AsyncInterceptor (>= 2.1.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 9.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Options (>= 9.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 9.0.0)
- TCIS.Logging.Autofac (>= 1.0.0-rc.19)
- TCIS.Pluggable.Engine (>= 1.0.0-rc.19)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0-rc.19 | 0 | 8/13/2026 |
| 1.0.0-rc.18 | 0 | 8/13/2026 |
| 1.0.0-rc.17 | 0 | 8/13/2026 |
| 1.0.0-rc.16 | 0 | 8/13/2026 |
| 1.0.0-rc.15 | 35 | 8/12/2026 |
| 1.0.0-rc.14 | 38 | 8/12/2026 |
| 1.0.0-rc.13 | 42 | 8/11/2026 |
| 1.0.0-rc.12 | 50 | 8/10/2026 |
| 1.0.0-rc.11 | 62 | 7/28/2026 |
| 1.0.0-rc.10 | 53 | 7/24/2026 |
| 1.0.0-rc.9 | 57 | 7/21/2026 |
| 1.0.0-rc.8 | 51 | 7/21/2026 |
| 1.0.0-rc.7 | 52 | 7/17/2026 |
| 1.0.0-rc.6 | 63 | 7/7/2026 |
| 1.0.0-rc.5 | 63 | 7/7/2026 |