VSMEF004 Exported type missing importing constructor
A class that exports itself or has exported members must be instantiable by MEF. If the class defines non-default constructors, it must have either:
- A parameterless constructor, or
- A constructor annotated with
[ImportingConstructor]
The following class definition would produce a diagnostic from this rule:
[Export]
class Foo
{
public Foo(string parameter)
{
// Non-default constructor without [ImportingConstructor]
}
}
This class exports itself but only has a non-default constructor that is not annotated with [ImportingConstructor]. MEF cannot instantiate this class because it doesn't know how to provide the required string parameter.
Fixing the diagnostic
There are several ways to fix this diagnostic:
Option 1: Add a parameterless constructor
[Export]
class Foo
{
public Foo()
{
// Default constructor for MEF
}
public Foo(string parameter)
{
// Non-default constructor for other uses
}
}
Option 2: Annotate a constructor with [ImportingConstructor]
[Export]
class Foo
{
[ImportingConstructor]
public Foo(string parameter)
{
// MEF will satisfy the 'parameter' import
}
}
Option 3: Use importing constructor with MEF imports
[Export]
class Foo
{
[ImportingConstructor]
public Foo([Import] IService service)
{
// MEF will inject the required IService
}
}
Examples that trigger this rule
Class-level export with non-default constructor
[Export]
class Service
{
public Service(string connectionString) // ❌ Error: missing [ImportingConstructor]
{
}
}
Class with exported members and non-default constructor
class ServiceProvider
{
[Export]
public IService GetService() => new Service();
public ServiceProvider(string config) // ❌ Error: missing [ImportingConstructor]
{
}
}
Mixed static and instance exports
class MixedExports
{
[Export]
public static string StaticValue = "test"; // ✅ OK: static export
[Export]
public string InstanceValue { get; set; } // ❌ Requires instantiation
public MixedExports(string parameter) // ❌ Error: missing [ImportingConstructor]
{
}
}
Examples that do NOT trigger this rule
Class with only static exports
class StaticOnlyExports
{
[Export]
public static IService Service { get; } = new Service();
public StaticOnlyExports(string parameter) // ✅ OK: no instance exports
{
}
}
Class with default constructor
[Export]
class Service
{
public Service() // ✅ OK: default constructor
{
}
}
Class with importing constructor
[Export]
class Service
{
[ImportingConstructor]
public Service(string connectionString) // ✅ OK: has [ImportingConstructor]
{
}
}
Abstract class
[Export]
abstract class ServiceBase
{
public ServiceBase(string parameter) // ✅ OK: abstract classes are not instantiated
{
}
}
Applies to both MEF versions
This rule applies to both MEF v1 (System.ComponentModel.Composition) and MEF v2 (System.Composition) attributes:
// MEF v1
[System.ComponentModel.Composition.Export]
class Service
{
[System.ComponentModel.Composition.ImportingConstructor]
public Service(string parameter) { }
}
// MEF v2
[System.Composition.Export]
class Service
{
[System.Composition.ImportingConstructor]
public Service(string parameter) { }
}