找不到与约束匹配的导出:让我的 wpf 应用程序与 MEF 一起工作的问题
No exports were found that match the constraint: Issues getting my wpf application to work with MEF
我正在开发一个 WPF 应用程序,我想使用 MEF (Manageable Extensibility Framework) 构建我的项目。但问题是当我尝试 运行 我的应用程序时出现此错误:
No exports were found that match the constraint: ContractName
MyFooPluginA RequiredTypeIdentity
namespace.of.my.core.project.IFooPlugin
这是我继续创作的
相同的概念适用于 IBarPlugin 类型的所有插件项目。以下是我如何设置我的第一个插件项目:
FooView.xaml.cs
/// <summary>
/// Interaction logic for FooView.xaml
/// </summary>
[Export(typeof(IFooPlugin)), PartCreationPolicy(CreationPolicy.Any)]
[ExportMetadata("Name", "MyFooPluginA")]
public partial class FooView: UserControl, IFooPlugin
{
[ImportingConstructor]
public FooView(FooViewModel viewModel) //we initialize the view first, then the view model
{
InitializeComponent();
DataContext = viewModel;
}
}
FooViewModel:
[Export]
public class FooViewModel
{
[ImportingConstructor]
public FooViewModel(...) //Contains parameters for dependency injections
{
//doing some work here
}
}
我终于在主应用程序视图模型中加载了插件:
public class MainAppViewModel
{
/// <summary>
/// If one plugin of type IFooPlugin is found then it is loaded in this property
/// </summary>
public IFooPlugin FooPluginView
{
get
{
return _fooPluginView;
}
set
{
_fooPluginView= value;
RaisePropertyChanged(nameof(FooPluginView));
}
}
private IFooPlugin _fooPluginView;
/// <summary>
/// Stores the catalog of all exported dlls
/// </summary>
private AggregateCatalog catalog;
/// <summary>
/// Stores the catalog information and all its parts
/// </summary>
private CompositionContainer Container;
public MainAppViewModel()
{
InitPlugin();//first thing I want it to do
if (someConditon == true)
{
FooPluginView = Container.GetExport<IFooPlugin>("MyFooPluginA").Value;
}
else
{
FooPluginView = Container.GetExport<IFooPlugin>("MyFooPluginA").Value;
}
}
private void InitPlugin()
{
//First create a catalog of exports
//It can be TypeCatalog(typeof(ISomeView), typeof(SomeOtherImportType))
//to search for all exports by specified types
//DirectoryCatalog(pluginsPath, "App*.dll") to search specified directories
//and matching specified file name
//An aggregate catalog that combines multiple catalogs
catalog = new AggregateCatalog();
//Here we add all the parts found in all assemblies in directory of executing assembly directory
//with file name matching Plugin*.dll
string pluginsPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
catalog.Catalogs.Add(new DirectoryCatalog(pluginsPath, "*Plugin.dll"));
//also we add to a search path a subdirectory plugins
pluginsPath = Path.Combine(pluginsPath, "Plugins");
catalog.Catalogs.Add(new DirectoryCatalog(pluginsPath, "*Plugin.dll"));
//Create the CompositionContainer with the parts in the catalog.
Container = new CompositionContainer(catalog);
//Fill the imports of this object
//finds imports and fills in all preperties decorated
//with Import attribute in this instance
Container.ComposeParts(this);
}
}
恐怕这可能不是您想要的确切答案,但据我所知 [ExportMetadata] 的属性值没有设置 ContractName。它的值被分配为元数据。所以,你可以改变
FooPluginView = Container.GetExport<IFooPlugin>("MyFooPluginA").Value;
到
FooPluginView = Container.GetExports<IFooPlugin, IDictionary<string, object>>().Where(x => (string)x.Metadata["Name"] == "MyFooPluginA").FirstOrDefault().Value;
或类似的。另外,您似乎没有将参数传递给 ImportingConstructor。我尝试了 MEF Constructor Injection 中针对您的情况解释的解决方案,例如
[ImportingConstructor]
public UserControl1([Import("DI")]FooViewModel viewModel)
Container.ComposeExportedValue("DI",new FooViewModel(null));
FooPluginView = Container.GetExports<IFooPlugin, IDictionary<string, object>>().Where(x => (string)x.Metadata["Name"] == "MyFooPluginA").FirstOrDefault().Value;
它在我的环境中运行良好。希望对您有所帮助。
我正在开发一个 WPF 应用程序,我想使用 MEF (Manageable Extensibility Framework) 构建我的项目。但问题是当我尝试 运行 我的应用程序时出现此错误:
No exports were found that match the constraint: ContractName MyFooPluginA RequiredTypeIdentity namespace.of.my.core.project.IFooPlugin
这是我继续创作的
相同的概念适用于 IBarPlugin 类型的所有插件项目。以下是我如何设置我的第一个插件项目:
FooView.xaml.cs
/// <summary>
/// Interaction logic for FooView.xaml
/// </summary>
[Export(typeof(IFooPlugin)), PartCreationPolicy(CreationPolicy.Any)]
[ExportMetadata("Name", "MyFooPluginA")]
public partial class FooView: UserControl, IFooPlugin
{
[ImportingConstructor]
public FooView(FooViewModel viewModel) //we initialize the view first, then the view model
{
InitializeComponent();
DataContext = viewModel;
}
}
FooViewModel:
[Export]
public class FooViewModel
{
[ImportingConstructor]
public FooViewModel(...) //Contains parameters for dependency injections
{
//doing some work here
}
}
我终于在主应用程序视图模型中加载了插件:
public class MainAppViewModel
{
/// <summary>
/// If one plugin of type IFooPlugin is found then it is loaded in this property
/// </summary>
public IFooPlugin FooPluginView
{
get
{
return _fooPluginView;
}
set
{
_fooPluginView= value;
RaisePropertyChanged(nameof(FooPluginView));
}
}
private IFooPlugin _fooPluginView;
/// <summary>
/// Stores the catalog of all exported dlls
/// </summary>
private AggregateCatalog catalog;
/// <summary>
/// Stores the catalog information and all its parts
/// </summary>
private CompositionContainer Container;
public MainAppViewModel()
{
InitPlugin();//first thing I want it to do
if (someConditon == true)
{
FooPluginView = Container.GetExport<IFooPlugin>("MyFooPluginA").Value;
}
else
{
FooPluginView = Container.GetExport<IFooPlugin>("MyFooPluginA").Value;
}
}
private void InitPlugin()
{
//First create a catalog of exports
//It can be TypeCatalog(typeof(ISomeView), typeof(SomeOtherImportType))
//to search for all exports by specified types
//DirectoryCatalog(pluginsPath, "App*.dll") to search specified directories
//and matching specified file name
//An aggregate catalog that combines multiple catalogs
catalog = new AggregateCatalog();
//Here we add all the parts found in all assemblies in directory of executing assembly directory
//with file name matching Plugin*.dll
string pluginsPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
catalog.Catalogs.Add(new DirectoryCatalog(pluginsPath, "*Plugin.dll"));
//also we add to a search path a subdirectory plugins
pluginsPath = Path.Combine(pluginsPath, "Plugins");
catalog.Catalogs.Add(new DirectoryCatalog(pluginsPath, "*Plugin.dll"));
//Create the CompositionContainer with the parts in the catalog.
Container = new CompositionContainer(catalog);
//Fill the imports of this object
//finds imports and fills in all preperties decorated
//with Import attribute in this instance
Container.ComposeParts(this);
}
}
恐怕这可能不是您想要的确切答案,但据我所知 [ExportMetadata] 的属性值没有设置 ContractName。它的值被分配为元数据。所以,你可以改变
FooPluginView = Container.GetExport<IFooPlugin>("MyFooPluginA").Value;
到
FooPluginView = Container.GetExports<IFooPlugin, IDictionary<string, object>>().Where(x => (string)x.Metadata["Name"] == "MyFooPluginA").FirstOrDefault().Value;
或类似的。另外,您似乎没有将参数传递给 ImportingConstructor。我尝试了 MEF Constructor Injection 中针对您的情况解释的解决方案,例如
[ImportingConstructor]
public UserControl1([Import("DI")]FooViewModel viewModel)
Container.ComposeExportedValue("DI",new FooViewModel(null));
FooPluginView = Container.GetExports<IFooPlugin, IDictionary<string, object>>().Where(x => (string)x.Metadata["Name"] == "MyFooPluginA").FirstOrDefault().Value;
它在我的环境中运行良好。希望对您有所帮助。