Design a service override and plan its registration
Add behavior behind a narrow interface, register it in the supported composition root, and verify the resolved service. Avoid a broad replacement whose scope is unknown.
In this guide
Define the smallest owned behavior
Begin with a single decision that is not client policy, such as rejecting a blank external reference. Keep the platform service call outside the example until the concrete extension seam is reviewed.
ExternalReferencePolicy.cs csharp
using System;
using Autofac;
using Znode.Libraries.Framework.Business;
public interface IExternalReferencePolicy
{
bool IsAcceptable(string value);
}
public sealed class ExternalReferencePolicy : IExternalReferencePolicy
{
public bool IsAcceptable(string value)
{
return !string.IsNullOrWhiteSpace(value) && value.Trim().Length <= 40;
}
}
public sealed class DependencyRegistration : IDependencyRegistration
{
public void Register(ContainerBuilder builder)
{
builder.RegisterType<ExternalReferencePolicy>()
.As<IExternalReferencePolicy>()
.InstancePerRequest();
}
public int Order { get { return 1; } }
}
Register at the intended boundary
Find the project's real composition root and determine whether it supports replacement, decoration, or additive registration. Put the registration in one obvious location. Do not construct the service with new at call sites because that bypasses lifecycle and test seams.
Prove resolution before behavior
Write one focused test that resolves the interface through the application container and confirms the expected implementation type. Then test accepted, blank, and too-long values. Finally exercise the concrete request that calls the policy, because a passing unit test does not prove the override was wired into the application path. A common failure is a valid class that is never registered, leaving the base service active without an error.
Distinguish your interface from the platform seam
The interface in this recipe is application-owned. It is safe to name, version, and unit-test because its contract is defined here. The registration is a concrete Autofac pattern used by Znode 9 custom projects: RegisterType<T>().As<TInterface>().InstancePerRequest() and a custom registration order of 1. When replacing a platform service, substitute the actual installed platform interface and custom class in that same registration shape.
When an override calls platform behavior, prefer delegation over replacement. Define which inputs the override validates, which behavior it leaves to the base implementation, and which errors it returns unchanged. Test registration ordering with the real container, then regression-test a request that should retain base behavior. That prevents a narrow rule from accidentally replacing authorization, caching, or other surrounding behavior.
References and further reading
Bring your next engineering question.
Need an extension seam reviewed before implementation?
Independent guidance from GCG. Znode is a trademark of its owner. Examples use fictional data and are not official platform documentation. Suggest a correction.