dotnet/BenchmarkDotNet · error · NotSupportedException
Custom factory must have a public parameterless constructor
Error message
Custom factory must have a public parameterless constructor
What it means
GetEngineFactoryTypeName emits, into the generated harness, the concrete type name of the configured IEngineFactory so the harness can `new` it up via reflection-free source. For that the factory type must expose a public parameterless constructor. If the resolved InfrastructureMode.EngineFactoryCharacteristic points at a type whose only constructors take parameters (or are non-public), NotSupportedException is thrown.
Source
Thrown at src/BenchmarkDotNet/Code/CodeGenerator.cs:244
private global::BenchmarkDotNet.Autogenerated.Runnable_$ID$.FieldsContainer __fieldsContainer;
*/
private static string GetInitializeArgumentFields(BenchmarkCase benchmarkCase)
=> string.Join(
Environment.NewLine,
benchmarkCase.Descriptor.WorkloadMethod.GetParameters()
.Select((parameter, index) => $"this.__fieldsContainer.argField{index} = {benchmarkCase.Parameters.GetArgument(parameter.Name!).ToSourceCode()};")); // we init the fields in ctor to provoke all possible allocations and overhead of other type
private static string GetEngineFactoryTypeName(BenchmarkCase benchmarkCase)
{
var factory = benchmarkCase.Job.ResolveValue(InfrastructureMode.EngineFactoryCharacteristic, InfrastructureResolver.Instance)!;
var factoryType = factory.GetType();
if (!factoryType.GetTypeInfo().DeclaredConstructors.Any(ctor => ctor.IsPublic && !ctor.GetParameters().Any()))
{
throw new NotSupportedException("Custom factory must have a public parameterless constructor");
}
return factoryType.GetCorrectCSharpTypeName();
}
private static string GetInProcessDiagnoserRouters(BenchmarkBuildInfo buildInfo)
{
var compositeInProcessDiagnoser = buildInfo.CompositeInProcessDiagnoser;
var handlerData = compositeInProcessDiagnoser.GetHandlerData(buildInfo.BenchmarkCase);
var sourceCodes = compositeInProcessDiagnoser.InProcessDiagnosers
.Select((diagnoser, index) => ToSourceCode(diagnoser, handlerData[index], buildInfo.BenchmarkCase, index))
.WhereNotNull();
return string.Join($",\n", sourceCodes);
static string? ToSourceCode(IInProcessDiagnoser diagnoser, InProcessDiagnoserHandlerData handlerData, BenchmarkCase benchmarkCase, int index)
{
if (handlerData.HandlerType is null)
{View on GitHub (pinned to b515068b61)
Solutions
- Add a public parameterless constructor to the custom factory type.
- Move configuration out of ctor parameters into settable properties or static/config read inside the factory.
- If you need runtime data, read it from the IEngine reference the factory receives at Run/create time rather than the ctor.
- Verify with factoryType.GetConstructors() that a public parameterless ctor exists before configuring it.
Example fix
// before
class MyFactory : IEngineFactory
{
public MyFactory(EngineOptions opts) { }
public IEngine Create() => ...;
}
// after
class MyFactory : IEngineFactory
{
public MyFactory() { }
public IEngine Create() => /* read options from a static/config source */ ...;
} Defensive patterns
Strategy: validation
Validate before calling
var factoryType = factory.GetType();
bool ok = factoryType.GetTypeInfo().DeclaredConstructors
.Any(c => c.IsPublic && !c.GetParameters().Any());
if (!ok)
throw new InvalidOperationException($"{factoryType} needs a public parameterless ctor.");
config.WithEngineFactory(factory); Type guard
static bool HasPublicParameterlessCtor<T>() where T : IEngineFactory
=> typeof(T).GetTypeInfo().DeclaredConstructors.Any(c => c.IsPublic && !c.GetParameters().Any()); Try / catch
try { /* run benchmark with custom factory */ }
catch (NotSupportedException ex) when (ex.Message.Contains("parameterless constructor"))
{
// add a public parameterless ctor to the factory type and rebuild
} Prevention
- Always give custom IEngineFactory implementations a public parameterless constructor.
- Do not rely on constructor DI for factories; read options at Create/Run time.
- Verify ctor presence with a reflection check in tests before configuring the factory.
When it happens
Trigger: Configuring a custom IEngineFactory implementation that has no public parameterless ctor, e.g. `class MyFactory : IEngineFactory { public MyFactory(SomeDep d){} }`, via .WithEngineFactory(...) or a custom job.
Common situations: Writing a custom in-process or hosting engine factory with dependency-injection constructors, or a factory that stores configuration in fields set via ctor params.
Related errors
- async void is not supported by design
- Please use Targets property
- Field 'ConsoleRunnerPackage' not found.
- Unable to get value of 'ConsoleRunnerPackage'.
- Method 'GetRunnerPath' not found.
AI-assisted analysis of dotnet/BenchmarkDotNet@b515068b61 (2026-08-13).
Data as JSON: /api/errors/7ac1594dbbb8c67d.
Report an issue: GitHub.