Home > Software design >  Autofac.Core.Registration.ComponentNotRegisteredException even the interface seems to be registered
Autofac.Core.Registration.ComponentNotRegisteredException even the interface seems to be registered

Time:01-11

I try to implement a WPF application using dependency injection and the MVVM pattern using the frameworks "CommunityFramework.MVVM" and "Autofac".

What I have so far is the the following(shows only the required parts):

  • in Main Project. Namespace: .UI.WPF
public class App : Application
{
    private IContainer _container;

    public App()
    {
        _builder = new ContainerBuilder();
        var assembly = Assembly.GetAssembly(typeof(Installer));
        string fullPath = assembly!.Location;
        string dir = Path.GetDirectoryName(fullPath)!;

        _builder.RegisterAssemblyModules(assembly);

        var assemblyPath = Path.Combine(dir, "ViewModel.dll");
        Debug.Assert(File.Exists(assemblyPath));
        assembly = Assembly.LoadFile(assemblyPath);
        _builder.RegisterAssemblyModules(assembly);

         assemblyPath = Path.Combine(dir, "Model.dll");
         Debug.Assert(File.Exists(assemblyPath));
         assembly = Assembly.LoadFile(assemblyPath);
         builder.RegisterAssemblyModules(assembly);

         _container = _builder.Build();
    }
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var start = _container?.Resolve<IShell<IMainWindow>>();
        // HERE the Exception occcures !!!
        var workSpace = _container?.Resolve<IMainWindowViewModel>();

        ....
    }
}

public interface IShell<T> where T:class
{
    // some defines here
}

public class Shell : IShell<IMainWindow>
{
    public Shell()
    {
        // some initialization here
    }
}
public class Installer : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        // Shell
        object ret = builder.RegisterType<Shell>()
            .As<IShell<IMainWindow>>()
            .SingleInstance();

        // Messanger
        builder.Register(_ => MessageListener.Listen().Messenger)
            .As<IMessenger>()
            .SingleInstance();
    }
}
  • in Project ViewModel: Namespace: .ViewModel
public class Installer : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        // MainWindowViewModel
        builder.RegisterType<MainWindowViewModel>()
            .As<IMainWindowViewModel>()
        .    SingleInstance();
    }
}

public interface IMainWindowViewModel
{
    // some entries here
}

public class MainWindowViewModel : ObservableRecipient, IMainWindowViewModel
{
    private IMessenger _messenger;
    private IMyProjectData_data;

    public MainWindowViewModel(IMyProjectDatadata, IMessenger messenger)
        : base(messenger)
    {
        _data = data;
        _messenger = messenger;
    }
}

  • in Project Model: Namespace: .Models
public class Installer : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        // Foto-Renamer Data
        builder.RegisterType<MyProjectData>()
            .As<IMyProjectData>()
            .SingleInstance();

        // Setings
        builder.RegisterType<Settings>()
            .As<ISettings>().
            SingleInstance();
    }
}

public interface IMyProjectData
{
    // some entries here
}

public partial class MyProjectData : ObservableObject, IMyProjectData
{
    private ISettings _settings;

    public MyProjectData(ISettings settings)
    {
        _settings = settings;
        // more initialization here
    }
}

public interface ISettings
{
    // some entries here
}

public class Settings : ISettings
{
    private IShell<IWindow> _shell;

    public Settings(IShell<IMainWindow> shell)
    {
        _shell = shell;
        //more initializations here
    }
}

At the marked Point i get the following exeption:

EDIT:

Exception:

Autofac.Core.DependencyResolutionException: "An exception was thrown while activating MyProject.ViewModel.MainWindowViewModel."

Stack trace:

at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action1 next) at Autofac.Core.Resolving.Middleware.SharingMiddleware.<>c__DisplayClass5_0.<Execute>b__0() at Autofac.Core.Lifetime.LifetimeScope.CreateSharedInstance(Guid id, Func1 creator) at Autofac.Core.Lifetime.LifetimeScope.CreateSharedInstance(Guid primaryId, Nullable1 qualifyingId, Func1 creator) at Autofac.Core.Resolving.Middleware.SharingMiddleware.Execute(ResolveRequestContext context, Action1 next) at Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(ResolveRequestContext context, Action1 next) at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest request) at Autofac.Core.Resolving.ResolveOperation.ExecuteOperation(ResolveRequest request) at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable1 parameters, Object& instance) at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable1 parameters) at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable`1 parameters) at MyProject.UI.WPF.App.OnStartup(StartupEventArgs e) in F:\Projects\MyProject\UI\MyProject.UI.WPF\App.xaml.cs: Zeile64 at System.Windows.Application.<.ctor>b__1_0(Object unused) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)

Inner exeption:

Autofac.Core.DependencyResolutionException: "None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyProject.ViewModel.MainWindowViewModel' can be invoked with the available services and parameters: Cannot resolve parameter 'MyProject.Model.Interfaces.IMyProjectData data' of constructor 'Void .ctor(MyProject.Model.Interfaces.IMyProjectData, CommunityToolkit.Mvvm.Messaging.IMessenger)'."

Stack trace inner exception:

at Autofac.Core.Activators.Reflection.ReflectionActivator.<>c__DisplayClass12_0.b__0(ResolveRequestContext ctxt, Action1 next) at Autofac.Core.Resolving.Middleware.DisposalTrackingMiddleware.Execute(ResolveRequestContext context, Action1 next) at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)

I checked that all three "Installer"-classes are reached and the registration is executed properly. At the point of the exception I tryed the container: All servicec can be resolved, expected:

_container.Resolve<IMyProjectData>() and

_container.Resolve<ISettings>() (this is required as parameter for IMyProjectData.ctor)

Can anybody see why the exception raises? It seems I'm blind for the moment! Thank you in advance for your response.

CodePudding user response:

The problem is that you have 2 instances of FotoRenamer.Model.dll loaded.

If you set a breakpoint on the faulting line and then open Debug->Windows->Modules you will see it. It's caused by loading the assemblies with Assembly.LoadFile(). The assemblies loaded this way are loaded into different load context (see https://learn.microsoft.com/en-us/dotnet/framework/deployment/best-practices-for-assembly-loading?source=recommendations for details about load contexts).

Since all assemblies are referenced by the main project you don't need to load them. The fix is simple:

    public static void InstallAutofac(ContainerBuilder builder)
    {
        var assembly = Assembly.GetAssembly(typeof(Installer));
        builder.RegisterAssemblyModules(assembly);

        assembly = Assembly.GetAssembly(typeof(ViewModel.Installer));
        builder.RegisterAssemblyModules(assembly);

        assembly = Assembly.GetAssembly(typeof(Model.Installer));
        builder.RegisterAssemblyModules(assembly);
    }
  • Related