Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MEF [ImportingConstructor] not called until [Import(AllowDefault = true)] is used

I am using MEF1 and running in to an odd scenerio.

This constructor is never called:

[ImportingConstructor]
public LogViewModuleRoot(INavigationCommandManager navigationCommandManager,
                         ISettingsManager settingsManager,
                         IBusyService busyService)
{
    NavigationCommandManager = navigationCommandManager;
    SettingsManager = settingsManager;
    BusyService = busyService;
}

While the constructor is called with the correct value when changed to this:

[ImportingConstructor]
public LogViewModuleRoot(INavigationCommandManager navigationCommandManager,
                         ISettingsManager settingsManager,
                         [Import(AllowDefault = true)] IBusyService busyService)
{
    NavigationCommandManager = navigationCommandManager;
    SettingsManager = settingsManager;
    BusyService = busyService; // Properly hydrated - i.e. not null
}

Typically, an ImportingConstructor does not get called if there is not a matching export, but if there was no matching export, then it would not be able to load when AllowDefault is set to true either.

What issues could cause this behavior?

If this has to do with a circular dependency within the composition graph and the timing of the construction of the IBusyService, are there tools to find the root of the problem?

Update

It seems like there is no deep circular dependency. Even when the export of IBusyService has no imports of it's own the problem still exists. Also note, the instance of IBusyService that is exported is loaded long before this ImportingConstructor tries to run.

Additional Information

Using MEFX Visualizer, both cases show that there are no composition problems and that all imports are satisfied.

This is the output of MEFX CompositionInfo:

[Part] ****.Modularity.Logging.CallbackLogger from: AssemblyCatalog (Assembly="****.Modularity.Mef, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Export] ****.Modularity.Logging.CallbackLogger (ContractName="****.Modularity.Logging.CallbackLogger")

[Part] ****.Modularity.Modules.ModuleManager from: AssemblyCatalog (Assembly="****.Modularity.Mef, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Export] ****.Modularity.Modules.ModuleManager (ContractName="****.Modularity.Modules.IModuleManager")
  [Import] ****.Modularity.Modules.ModuleManager.ImportedModules (ContractName="****.Modularity.IModule")
    [SatisfiedBy] Debug.Module.ModuleRoot (ContractName="****.Modularity.IModule") from: Debug.Module.ModuleRoot from: AssemblyCatalog (Assembly="Debug.Module, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
    [Unsuitable] Logging.Module.LogConfigurationModuleRoot (ContractName="****.Modularity.IModule") from: Logging.Module.LogConfigurationModuleRoot from: AssemblyCatalog (Assembly="Logging.Module, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
    [Unsuitable] Logging.Module.LogViewModuleRoot (ContractName="****.Modularity.IModule") from: Logging.Module.LogViewModuleRoot from: AssemblyCatalog (Assembly="Logging.Module, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
  [Import] ****.Modularity.Modules.ModuleManager..ctor (Parameter="moduleCatalog", ContractName="****.Modularity.Modules.IModuleCatalog")
    [SatisfiedBy] ****.Modularity.Modules.IModuleCatalog
  [Import] ****.Modularity.Modules.ModuleManager..ctor (Parameter="logger", ContractName="****.Modularity.Logging.ILogger")
    [SatisfiedBy] ****.Modularity.Logging.ILogger
  [Import] ****.Modularity.Modules.ModuleManager..ctor (Parameter="exServiceLocator", ContractName="****.Modularity.IExtendedServiceLocator")
    [SatisfiedBy] ****.Modularity.IExtendedServiceLocator

[Part] ****.Modularity.Shells.ConsoleShell from: AssemblyCatalog (Assembly="****.Modularity.Shells, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
  [Export] ****.Modularity.Shells.ConsoleShell (ContractName="****.Modularity.Shells.ConsoleShell")
  [Import] ****.Modularity.Shells.ConsoleShell..ctor (Parameter="navigationManager", ContractName="****.Modularity.Windows.Navigation.INavigationManager")
    [SatisfiedBy] ****.Modularity.Windows.Navigation.NavigationManager (ContractName="****.Modularity.Windows.Navigation.INavigationManager") from: ****.Modularity.Windows.Navigation.NavigationManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Import] ****.Modularity.Shells.ConsoleShell..ctor (Parameter="logger", ContractName="****.Modularity.Logging.CallbackLogger")
    [SatisfiedBy] ****.Modularity.Logging.CallbackLogger (ContractName="****.Modularity.Logging.CallbackLogger") from: ****.Modularity.Logging.CallbackLogger from: AssemblyCatalog (Assembly="****.Modularity.Mef, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Import] ****.Modularity.Shells.ConsoleShell..ctor (Parameter="locator", ContractName="****.Modularity.IExtendedServiceLocator")
    [SatisfiedBy] ****.Modularity.IExtendedServiceLocator
  [Import] ****.Modularity.Shells.ConsoleShell..ctor (Parameter="viewModel", ContractName="****.Modularity.Shells.ViewModel.ShellViewModel")
    [SatisfiedBy] ****.Modularity.Shells.ViewModel.ShellViewModel (ContractName="****.Modularity.Shells.ViewModel.ShellViewModel") from: ****.Modularity.Shells.ViewModel.ShellViewModel from: AssemblyCatalog (Assembly="****.Modularity.Shells, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

[Part] ****.Modularity.Shells.****LegacyNavigation from: AssemblyCatalog (Assembly="****.Modularity.Shells, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
  [Export] ****.Modularity.Shells.****LegacyNavigation (ContractName="****.Modularity.Shells.****LegacyNavigation")
  [Import] ****.Modularity.Shells.****LegacyNavigation..ctor (Parameter="navigationManager", ContractName="****.Modularity.Windows.Navigation.INavigationManager")
    [SatisfiedBy] ****.Modularity.Windows.Navigation.NavigationManager (ContractName="****.Modularity.Windows.Navigation.INavigationManager") from: ****.Modularity.Windows.Navigation.NavigationManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Import] ****.Modularity.Shells.****LegacyNavigation..ctor (Parameter="logger", ContractName="****.Modularity.Logging.CallbackLogger")
    [SatisfiedBy] ****.Modularity.Logging.CallbackLogger (ContractName="****.Modularity.Logging.CallbackLogger") from: ****.Modularity.Logging.CallbackLogger from: AssemblyCatalog (Assembly="****.Modularity.Mef, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Import] ****.Modularity.Shells.****LegacyNavigation..ctor (Parameter="locator", ContractName="****.Modularity.IExtendedServiceLocator")
    [SatisfiedBy] ****.Modularity.IExtendedServiceLocator
  [Import] ****.Modularity.Shells.****LegacyNavigation..ctor (Parameter="dataContext", ContractName="****.Modularity.Windows.Shell.IShellDataContext")
    [SatisfiedBy] ****.Modularity.Shells.ViewModel.ShellViewModel (ContractName="****.Modularity.Windows.Shell.IShellDataContext") from: ****.Modularity.Shells.ViewModel.ShellViewModel from: AssemblyCatalog (Assembly="****.Modularity.Shells, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

[Part] ****.Modularity.Shells.KioskShell from: AssemblyCatalog (Assembly="****.Modularity.Shells, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
  [Export] ****.Modularity.Shells.KioskShell (ContractName="****.Modularity.Shells.KioskShell")
  [Import] ****.Modularity.Shells.KioskShell..ctor (Parameter="navigationManager", ContractName="****.Modularity.Windows.Navigation.INavigationManager")
    [SatisfiedBy] ****.Modularity.Windows.Navigation.NavigationManager (ContractName="****.Modularity.Windows.Navigation.INavigationManager") from: ****.Modularity.Windows.Navigation.NavigationManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Import] ****.Modularity.Shells.KioskShell..ctor (Parameter="logger", ContractName="****.Modularity.Logging.CallbackLogger")
    [SatisfiedBy] ****.Modularity.Logging.CallbackLogger (ContractName="****.Modularity.Logging.CallbackLogger") from: ****.Modularity.Logging.CallbackLogger from: AssemblyCatalog (Assembly="****.Modularity.Mef, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Import] ****.Modularity.Shells.KioskShell..ctor (Parameter="dataContext", ContractName="****.Modularity.Windows.Shell.IShellDataContext")
    [SatisfiedBy] ****.Modularity.Shells.ViewModel.ShellViewModel (ContractName="****.Modularity.Windows.Shell.IShellDataContext") from: ****.Modularity.Shells.ViewModel.ShellViewModel from: AssemblyCatalog (Assembly="****.Modularity.Shells, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

[Part] ****.Modularity.Shells.ViewModel.ShellViewModel from: AssemblyCatalog (Assembly="****.Modularity.Shells, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
  [Export] ****.Modularity.Shells.ViewModel.ShellViewModel (ContractName="****.Modularity.Windows.Shell.IShellDataContext")
  [Export] ****.Modularity.Shells.ViewModel.ShellViewModel (ContractName="****.Modularity.Windows.Commanding.INavigationContext")
  [Export] ****.Modularity.Shells.ViewModel.ShellViewModel (ContractName="****.Modularity.Windows.IBusyService")
  [Export] ****.Modularity.Shells.ViewModel.ShellViewModel (ContractName="****.Modularity.Shells.ViewModel.ShellViewModel")
  [Import] ****.Modularity.Shells.ViewModel.ShellViewModel..ctor (Parameter="navigationCommandManager", ContractName="****.Modularity.Windows.Commanding.INavigationCommandManager")
    [SatisfiedBy] ****.Modularity.Windows.Commanding.INavigationCommandManager
    [Unsuitable] ****.Modularity.Windows.Commanding.NavigationCommandManager (ContractName="****.Modularity.Windows.Commanding.INavigationCommandManager") from: ****.Modularity.Windows.Commanding.NavigationCommandManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Import] ****.Modularity.Shells.ViewModel.ShellViewModel..ctor (Parameter="menuCommandManager", ContractName="****.Modularity.Windows.IMenuCommandManager")
    [SatisfiedBy] ****.Modularity.Windows.Commanding.MenuCommandManager (ContractName="****.Modularity.Windows.IMenuCommandManager") from: ****.Modularity.Windows.Commanding.MenuCommandManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Import] ****.Modularity.Shells.ViewModel.ShellViewModel..ctor (Parameter="applicationInformation", ContractName="****.Modularity.Shells.IApplicationInformation")
    [SatisfiedBy] ****.Modularity.Shells.IApplicationInformation
  [Import] ****.Modularity.Shells.ViewModel.ShellViewModel..ctor (Parameter="manager", ContractName="****.Modularity.Modules.IModuleManager")
    [SatisfiedBy] ****.Modularity.Modules.ModuleManager (ContractName="****.Modularity.Modules.IModuleManager") from: ****.Modularity.Modules.ModuleManager from: AssemblyCatalog (Assembly="****.Modularity.Mef, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Import] ****.Modularity.Shells.ViewModel.ShellViewModel..ctor (Parameter="actionExecuter", ContractName="****.Modularity.IActionExecuter")
    [SatisfiedBy] ****.Modularity.IActionExecuter

[Part] ****.Modularity.Windows.Commanding.MenuCommandManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Export] ****.Modularity.Windows.Commanding.MenuCommandManager (ContractName="****.Modularity.Windows.IMenuCommandManager")
  [Import] ****.Modularity.Windows.Commanding.MenuCommandManager..ctor (Parameter="moduleManager", ContractName="****.Modularity.Modules.IModuleManager")
    [SatisfiedBy] ****.Modularity.Modules.ModuleManager (ContractName="****.Modularity.Modules.IModuleManager") from: ****.Modularity.Modules.ModuleManager from: AssemblyCatalog (Assembly="****.Modularity.Mef, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
  [Import] ****.Modularity.Windows.Commanding.MenuCommandManager..ctor (Parameter="navigationManager", ContractName="****.Modularity.Windows.Navigation.INavigationManager")
    [SatisfiedBy] ****.Modularity.Windows.Navigation.NavigationManager (ContractName="****.Modularity.Windows.Navigation.INavigationManager") from: ****.Modularity.Windows.Navigation.NavigationManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")

    [Part] ****.Modularity.Windows.Commanding.NavigationCommandManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
      [Export] ****.Modularity.Windows.Commanding.NavigationCommandManager (ContractName="****.Modularity.Windows.Commanding.INavigationCommandManager")
      [Import] ****.Modularity.Windows.Commanding.NavigationCommandManager..ctor (Parameter="moduleManager", ContractName="****.Modularity.Modules.IModuleManager")
        [SatisfiedBy] ****.Modularity.Modules.ModuleManager (ContractName="****.Modularity.Modules.IModuleManager") from: ****.Modularity.Modules.ModuleManager from: AssemblyCatalog (Assembly="****.Modularity.Mef, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
      [Import] ****.Modularity.Windows.Commanding.NavigationCommandManager..ctor (Parameter="navigationManager", ContractName="****.Modularity.Windows.Navigation.INavigationManager")
        [SatisfiedBy] ****.Modularity.Windows.Navigation.NavigationManager (ContractName="****.Modularity.Windows.Navigation.INavigationManager") from: ****.Modularity.Windows.Navigation.NavigationManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")

    [Part] ****.Modularity.Windows.Commanding.MenuNavigationCommandManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
      [Export] ****.Modularity.Windows.Commanding.MenuNavigationCommandManager (ContractName="****.Modularity.Windows.Commanding.MenuNavigationCommandManager")
      [Import] ****.Modularity.Windows.Commanding.MenuNavigationCommandManager..ctor (Parameter="moduleManager", ContractName="****.Modularity.Modules.IModuleManager")
        [SatisfiedBy] ****.Modularity.Modules.ModuleManager (ContractName="****.Modularity.Modules.IModuleManager") from: ****.Modularity.Modules.ModuleManager from: AssemblyCatalog (Assembly="****.Modularity.Mef, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
      [Import] ****.Modularity.Windows.Commanding.MenuNavigationCommandManager..ctor (Parameter="navigationManager", ContractName="****.Modularity.Windows.Navigation.INavigationManager")
        [SatisfiedBy] ****.Modularity.Windows.Navigation.NavigationManager (ContractName="****.Modularity.Windows.Navigation.INavigationManager") from: ****.Modularity.Windows.Navigation.NavigationManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
      [Import] ****.Modularity.Windows.Commanding.MenuNavigationCommandManager..ctor (Parameter="menuCommandManager", ContractName="****.Modularity.Windows.IMenuCommandManager")
        [SatisfiedBy] ****.Modularity.Windows.Commanding.MenuCommandManager (ContractName="****.Modularity.Windows.IMenuCommandManager") from: ****.Modularity.Windows.Commanding.MenuCommandManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")

    [Part] ****.Modularity.Windows.Navigation.NavigationManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
      [Export] ****.Modularity.Windows.Navigation.NavigationManager (ContractName="****.Framework.ViewModel.INavigationService")
      [Export] ****.Modularity.Windows.Navigation.NavigationManager (ContractName="****.Modularity.Windows.Navigation.INavigationManager")
      [Import] ****.Modularity.Windows.Navigation.NavigationManager..ctor (Parameter="moduleManager", ContractName="****.Modularity.Modules.IModuleManager")
        [SatisfiedBy] ****.Modularity.Modules.ModuleManager (ContractName="****.Modularity.Modules.IModuleManager") from: ****.Modularity.Modules.ModuleManager from: AssemblyCatalog (Assembly="****.Modularity.Mef, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")

    [Part] Logging.Module.LogConfigurationModuleRoot from: AssemblyCatalog (Assembly="Logging.Module, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
      [Export] Logging.Module.LogConfigurationModuleRoot (ContractName="****.Modularity.IModule")
      [Import] Logging.Module.LogConfigurationModuleRoot..ctor (Parameter="logConfiguration", ContractName="Logging.ViewModel.Interfaces.ILogConfiguration")
        [SatisfiedBy] Logging.ViewModel.LogConfigurationViewModel (ContractName="Logging.ViewModel.Interfaces.ILogConfiguration") from: Logging.ViewModel.LogConfigurationViewModel from: AssemblyCatalog (Assembly="Logging.ViewModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

    [Part] Logging.Module.LogViewModuleRoot from: AssemblyCatalog (Assembly="Logging.Module, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
      [Export] Logging.Module.LogViewModuleRoot (ContractName="****.Modularity.IModule")
      [Import] Logging.Module.LogViewModuleRoot..ctor (Parameter="navigationCommandManager", ContractName="****.Modularity.Windows.Commanding.INavigationCommandManager")
        [SatisfiedBy] ****.Modularity.Windows.Commanding.INavigationCommandManager
        [Unsuitable] ****.Modularity.Windows.Commanding.NavigationCommandManager (ContractName="****.Modularity.Windows.Commanding.INavigationCommandManager") from: ****.Modularity.Windows.Commanding.NavigationCommandManager from: AssemblyCatalog (Assembly="****.Modularity.Windows, Version=2.4.0.347, Culture=neutral, PublicKeyToken=null")
      [Import] Logging.Module.LogViewModuleRoot..ctor (Parameter="settingsManager", ContractName="****.Modularity.ISettingsManager")
        [SatisfiedBy] ****.Modularity.ISettingsManager
      [Import] Logging.Module.LogViewModuleRoot..ctor (Parameter="busyService", ContractName="****.Modularity.Windows.IBusyService")
        [SatisfiedBy] ****.Modularity.Shells.ViewModel.ShellViewModel (ContractName="****.Modularity.Windows.IBusyService") from: ****.Modularity.Shells.ViewModel.ShellViewModel from: AssemblyCatalog (Assembly="****.Modularity.Shells, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

    [Part] Logging.ViewModel.LogConfigurationViewModel from: AssemblyCatalog (Assembly="Logging.ViewModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
      [Export] Logging.ViewModel.LogConfigurationViewModel (ContractName="Logging.ViewModel.Interfaces.ILogConfiguration")
      [Import] Logging.ViewModel.LogConfigurationViewModel..ctor (Parameter="viewModelManager", ContractName="****.Framework.ViewModel.ViewModelManager")
    [SatisfiedBy] ****.Framework.ViewModel.ViewModelManager

      [Import] Logging.ViewModel.LogConfigurationViewModel..ctor (Parameter="settingsManager", ContractName="****.Modularity.ISettingsManager")
        [SatisfiedBy] ****.Modularity.ISettingsManager
      [Import] Logging.ViewModel.LogConfigurationViewModel..ctor (Parameter="busyService", ContractName="****.Modularity.Windows.IBusyService")
        [SatisfiedBy] ****.Modularity.Shells.ViewModel.ShellViewModel (ContractName="****.Modularity.Windows.IBusyService") from: ****.Modularity.Shells.ViewModel.ShellViewModel from: AssemblyCatalog (Assembly="****.Modularity.Shells, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
      [Import] Logging.ViewModel.LogConfigurationViewModel..ctor (Parameter="actionExecuter", ContractName="****.Modularity.IActionExecuter")
        [SatisfiedBy] ****.Modularity.IActionExecuter

    [Part] Debug.Module.ModuleRoot from: AssemblyCatalog (Assembly="Debug.Module, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
      [Export] Debug.Module.ModuleRoot (ContractName="****.Modularity.IModule")
      [Import] Debug.Module.ModuleRoot..ctor (Parameter="container", ContractName="System.ComponentModel.Composition.Hosting.CompositionContainer")
        [SatisfiedBy] System.ComponentModel.Composition.Hosting.CompositionContainer
      [Import] Debug.Module.ModuleRoot..ctor (Parameter="catalogs", ContractName="System.ComponentModel.Composition.Primitives.ComposablePartCatalog")
        [SatisfiedBy] System.ComponentModel.Composition.Primitives.ComposablePartCatalog
      [Import] Debug.Module.ModuleRoot..ctor (Parameter="shell", ContractName="****.Modularity.Windows.Shell.IShellDataContext")
        [SatisfiedBy] ****.Modularity.Shells.ViewModel.ShellViewModel (ContractName="****.Modularity.Windows.Shell.IShellDataContext") from: ****.Modularity.Shells.ViewModel.ShellViewModel from: AssemblyCatalog (Assembly="****.Modularity.Shells, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
      [Import] Debug.Module.ModuleRoot..ctor (Parameter="settingsManager", ContractName="****.Modularity.ISettingsManager")
        [SatisfiedBy] ****.Modularity.ISettingsManager
like image 629
Nick Freeman Avatar asked Nov 04 '22 01:11

Nick Freeman


1 Answers

Since ShellViewModel exports IBusyService and LogViewModuleRoot imports IBusyService

You do have a pre-export (i.e. constructor imports) cycle:

ShellViewModel -> IModuleManager -> IModule(s) -> LogViewModuleRoot

The AllowDefault=true allows that cycle to break and the reason it isn't null is due to the order in which these get constructed. It is not deterministic and could very well be null in another case if you pull on the LogViewModuleRoot object first for example.

Probably the best way to break the cycle and ensure it is always set is to switch the IBusyService to a Property Import on LogViewModuleRoot.

like image 116
Wes Haggard Avatar answered Nov 15 '22 04:11

Wes Haggard