Caliburn micro 在使用 mef 时找不到 MainView
Caliburn micro cant find MainView when using mef
我现在有点懵。我在 MEF 中使用 Caliburn 微框架。
主应用程序应该加载基本上只包含服务功能的插件。但是一旦我引用外部程序集,CaliburnMicro 就会拒绝找到 MainWindowView(如果没有引用外部程序集,它会很好地工作)。
我的引导程序(基本上是 CM 示例中的引导程序):
public class AppBootstrapper : BootstrapperBase
{
private CompositionContainer container;
public AppBootstrapper()
{
Initialize();
}
protected override void Configure()
{
container = new CompositionContainer(
new AggregateCatalog(
AssemblySource.Instance.Select( x => new AssemblyCatalog( x ) ).OfType<ComposablePartCatalog>()
)
);
var batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>( new WindowManager() );
batch.AddExportedValue<IEventAggregator>( new EventAggregator() );
batch.AddExportedValue( container );
container.Compose( batch );
}
protected override object GetInstance( Type serviceType, string key )
{
var contract = string.IsNullOrEmpty( key ) ? AttributedModelServices.GetContractName( serviceType ) : key;
var exports = container.GetExportedValues<object>( contract );
if ( exports.Any() )
return exports.First();
throw new Exception( $"Could not locate any instances of contract {contract}." );
}
protected override IEnumerable<object> GetAllInstances( Type serviceType )
{
return container.GetExportedValues<object>( AttributedModelServices.GetContractName( serviceType ) );
}
protected override void BuildUp( object instance )
{
container.SatisfyImportsOnce( instance );
}
protected override void OnStartup( object sender, StartupEventArgs e )
{
base.OnStartup( sender, e );
DisplayRootViewFor<IMainWindow>();
}
}
我的主窗口
[Export( typeof( IMainWindow ) )]
public class MainWindowViewModel : Conductor<IShell>, IMainWindow, IPartImportsSatisfiedNotification
{
private string _title = "Title";
public string Title
{
get { return _title; }
set
{
_title = value;
NotifyOfPropertyChange( () => Title );
}
}
private ImageSource _icon;
public ImageSource Icon
{
get { return _icon; }
set
{
_icon = value;
NotifyOfPropertyChange( () => Icon );
}
}
[Import]
private IResourceManager _resourceManager;
[Import]
private IShell _shell;
public IShell Shell
{
get { return _shell; }
private set
{
_shell = value;
NotifyOfPropertyChange( () => Shell );
}
}
public void OnImportsSatisfied()
{
if ( Icon == null )
Icon = _resourceManager.GetBitmap( "Resources/Icons/icon.ico" );
}
}
Shell和ResourceManager在主assembly/executable中(与MainWindow/Bootstrapper相同)。
我尝试从外部程序集导出接口并使用 ShellViewModel 导入它。
我的ShellViewModel
[Export( typeof ( IShell ) )]
public class ShellViewModel : PropertyChangedBase, IShell
{
[Import]
private ITestInterface _testInterface;
public ITestInterface TestInterface
{
get { return _testInterface; }
set { _testInterface = value; }
}
}
我的外部程序集:
public interface ITestInterface
{
string Test();
}
[Export(typeof(ITestInterface))]
public class MyTest : ITestInterface
{
public string Test()
{
return "Test ok";
}
}
找到的解决方案:
protected override void Configure()
{
container = new CompositionContainer( new ApplicationCatalog() );
var batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>( new WindowManager() );
batch.AddExportedValue<IEventAggregator>( new EventAggregator() );
batch.AddExportedValue( container );
container.Compose( batch );
}
将 AggregateCatalog
更改为 ApplicationCatalog
解决了问题。
我现在有点懵。我在 MEF 中使用 Caliburn 微框架。 主应用程序应该加载基本上只包含服务功能的插件。但是一旦我引用外部程序集,CaliburnMicro 就会拒绝找到 MainWindowView(如果没有引用外部程序集,它会很好地工作)。
我的引导程序(基本上是 CM 示例中的引导程序):
public class AppBootstrapper : BootstrapperBase
{
private CompositionContainer container;
public AppBootstrapper()
{
Initialize();
}
protected override void Configure()
{
container = new CompositionContainer(
new AggregateCatalog(
AssemblySource.Instance.Select( x => new AssemblyCatalog( x ) ).OfType<ComposablePartCatalog>()
)
);
var batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>( new WindowManager() );
batch.AddExportedValue<IEventAggregator>( new EventAggregator() );
batch.AddExportedValue( container );
container.Compose( batch );
}
protected override object GetInstance( Type serviceType, string key )
{
var contract = string.IsNullOrEmpty( key ) ? AttributedModelServices.GetContractName( serviceType ) : key;
var exports = container.GetExportedValues<object>( contract );
if ( exports.Any() )
return exports.First();
throw new Exception( $"Could not locate any instances of contract {contract}." );
}
protected override IEnumerable<object> GetAllInstances( Type serviceType )
{
return container.GetExportedValues<object>( AttributedModelServices.GetContractName( serviceType ) );
}
protected override void BuildUp( object instance )
{
container.SatisfyImportsOnce( instance );
}
protected override void OnStartup( object sender, StartupEventArgs e )
{
base.OnStartup( sender, e );
DisplayRootViewFor<IMainWindow>();
}
}
我的主窗口
[Export( typeof( IMainWindow ) )]
public class MainWindowViewModel : Conductor<IShell>, IMainWindow, IPartImportsSatisfiedNotification
{
private string _title = "Title";
public string Title
{
get { return _title; }
set
{
_title = value;
NotifyOfPropertyChange( () => Title );
}
}
private ImageSource _icon;
public ImageSource Icon
{
get { return _icon; }
set
{
_icon = value;
NotifyOfPropertyChange( () => Icon );
}
}
[Import]
private IResourceManager _resourceManager;
[Import]
private IShell _shell;
public IShell Shell
{
get { return _shell; }
private set
{
_shell = value;
NotifyOfPropertyChange( () => Shell );
}
}
public void OnImportsSatisfied()
{
if ( Icon == null )
Icon = _resourceManager.GetBitmap( "Resources/Icons/icon.ico" );
}
}
Shell和ResourceManager在主assembly/executable中(与MainWindow/Bootstrapper相同)。
我尝试从外部程序集导出接口并使用 ShellViewModel 导入它。
我的ShellViewModel
[Export( typeof ( IShell ) )]
public class ShellViewModel : PropertyChangedBase, IShell
{
[Import]
private ITestInterface _testInterface;
public ITestInterface TestInterface
{
get { return _testInterface; }
set { _testInterface = value; }
}
}
我的外部程序集:
public interface ITestInterface
{
string Test();
}
[Export(typeof(ITestInterface))]
public class MyTest : ITestInterface
{
public string Test()
{
return "Test ok";
}
}
找到的解决方案:
protected override void Configure()
{
container = new CompositionContainer( new ApplicationCatalog() );
var batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>( new WindowManager() );
batch.AddExportedValue<IEventAggregator>( new EventAggregator() );
batch.AddExportedValue( container );
container.Compose( batch );
}
将 AggregateCatalog
更改为 ApplicationCatalog
解决了问题。