stride3d/stride · error · ArgumentException

The given type does have a public parameterless constructor.

Error message

The given type does have a public parameterless constructor.

What it means

After checking that factoryType implements IObjectFactory, ObjectFactoryAttribute requires a public parameterless constructor so the framework can instantiate the factory at runtime. When factoryType.GetConstructor(Type.EmptyTypes) returns null, the constructor throws ArgumentException. Note the message reads 'does have' but the intent is 'does NOT have' — an upstream wording quirk.

Solutions

  1. Add a public parameterless constructor to the factory class (it can chain to an overloaded one).
  2. Pass a concrete factory type that constructs its own dependencies.
  3. Ensure the class is not abstract and the default ctor is public, not private/internal.

Example fix

// before
public class MeshFactory : IObjectFactory
{
    public MeshFactory(ILogger log) { ... } // no parameterless ctor
}

// after
public class MeshFactory : IObjectFactory
{
    public MeshFactory() : this(null) { }
    public MeshFactory(ILogger log) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

if (factoryType.GetConstructor(Type.EmptyTypes) == null)
    throw new ArgumentException($"{factoryType} needs a public parameterless constructor", nameof(factoryType));
var attr = new ObjectFactoryAttribute(factoryType);

Type guard

static bool HasPublicParameterlessCtor(Type t) => t.GetConstructor(Type.EmptyTypes) != null;
// compile-time alternative: constrain generics with 'where TFactory : IObjectFactory, new()'

Prevention

When it happens

Trigger: Passing a factory class whose only constructors take parameters (e.g. DI-injected dependencies), an abstract factory base class, or a class with a private/internal default constructor.

Common situations: DI-style factories with constructor-injected dependencies; abstract base classes passed by mistake; a required constructor parameter added during a refactor.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/7e5dccf1f8a8715b. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core/Annotations/ObjectFactoryAttribute.cs:35

    /// <summary>
    /// The type of the factory to use to create instance of the related type.
    /// </summary>
    [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
    public Type FactoryType { get; }

    /// <summary>
    /// Initializes a new instance of the <see cref="ObjectFactoryAttribute"/> class.
    /// </summary>
    /// <param name="factoryType">The factory type that implements <see cref="IObjectFactory"/>.</param>
    public ObjectFactoryAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type factoryType)
    {
#if NET7_0_OR_GREATER
        ArgumentNullException.ThrowIfNull(factoryType);
#else
        if (factoryType is null) throw new ArgumentNullException(nameof(factoryType));
#endif // NET7_0_OR_GREATER
        if (!typeof(IObjectFactory).GetTypeInfo().IsAssignableFrom(factoryType.GetTypeInfo())) throw new ArgumentException($"The given type does not implement {nameof(IObjectFactory)}/", nameof(factoryType));
        if (factoryType.GetTypeInfo().GetConstructor(Type.EmptyTypes) == null) throw new ArgumentException("The given type does have a public parameterless constructor.", nameof(factoryType));
        FactoryType = factoryType;
    }
}

View on GitHub (pinned to 96fad776d2)