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

  1. Add a public parameterless constructor to the custom factory type.
  2. Move configuration out of ctor parameters into settable properties or static/config read inside the factory.
  3. If you need runtime data, read it from the IEngine reference the factory receives at Run/create time rather than the ctor.
  4. 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

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


AI-assisted analysis of dotnet/BenchmarkDotNet@b515068b61 (2026-08-13). Data as JSON: /api/errors/7ac1594dbbb8c67d. Report an issue: GitHub.