任何人都可以通过相关示例帮助我使用MEF中的Import和ImportingConstructor属性以及何时使用? [Import(AllowDefault = true)]的用途是什么?
根据我对MEF的理解:
导出属性是在类型T的类上定义的,其中T是接口,并且要创建该类的实例,应该在引用变量上定义导入属性,如下所示
[Export(typeof(ICalculator))]
class MySimpleCalculator : ICalculator
{
// Implement the interface
}
class MyMainClass
{
// MEF engine creates an instance as Export attribute is defined
// on MySimpleCalculator
[Import(typeof(ICalculator))]
public ICalculator calculator;
}
如果在给定程序集中定义了T类型的多个导出,那么我们可以使用ImportMany属性。
那么现在有人可以解释何时在构造函数中使用Import和ImportingConstructor以及AllowDefault属性?
如果有人可以用更好的例子来解释,那就太好了。
任何帮助将不胜感激。 感谢
答案 0 :(得分:1)
<强> ImportingConstructor 强>
在示例代码中导入/导出部件的方式,如果MyMainClass
正在组合,则调用隐式无参数构造函数,然后分配MySimpleCalculator
的实例到calculator
字段。
现在让我们假设你想要一个readonly字段/ get-only属性,或者需要访问构造函数中的ICalculator
,你需要将它传递给构造函数而不是比以后分配到该领域:
public interface ICalculator
{
bool Quack { get; }
}
[Export(typeof(ICalculator))]
public class MySimpleCalculator : ICalculator
{
public bool Quack => true;
}
[Export]
public class MyMainClass
{
public ICalculator Calculator { get; }
public string Blah { get; }
[ImportingConstructor]
public MyMainClass(ICalculator calculator)
{
Calculator = calculator; // assign readonly property
Blah = calculator.Quack ? "Foo" : "Bar"; // do something based on calculator
}
}
现在隐式导入构造函数的参数并使用相应的导出来满足。
<强> AllowDefault 强>
如果您[导入]某些东西,那些东西必须可用或合成失败。
如果你[导入(AllowDefault = true)]某事,组成不会&#39;如果没有相应的导出,则会失败,但是导入的值为null / false / 0。
顺便说一句:抱歉有点讽刺,但答案也可能是RTFM。答案 1 :(得分:0)
在您的应用程序中,MEF包含三个基本部分。如果继续进行笔记本电脑的类比,我们可以将这三个部分可视化为笔记本电脑上的USB端口,带有USB连接器的外部硬盘驱动器以及将USB连接器插入端口的手。用MEF术语,将端口定义为[Import]语句。该语句放在属性上方,以告诉系统此处插入了某些内容。 USB电缆定义为[Export]语句。该语句放在类,方法或属性的上方,指示这是要插入某处的项目。一个应用程序可能会(并且可能会)包含许多此类进出口。第三部分的工作是弄清楚我们拥有哪些端口,以及因此需要插入哪些电缆。这是CompositionContainer的工作。它就像手一样,插入与相应端口匹配的电缆。那些与端口不匹配的电缆将被忽略。
[ImportMany] // It allows us to import zero or more Exported items that match.
private IEnumerable<Lazy<IProvider, IMetaData>> _Providers;
[Export] // This tag is required if you want to create an instance in the child class
private readonly IFacade _iFacade;
#region [ MEF Loading ]
private void LoadPlugin()
{
var pluginsDirectoryPath = ConfigurationReader.PluginsDirectoryPath;
if (System.IO.Path.IsPathRooted(pluginsDirectoryPath) == false)
pluginsDirectoryPath =
System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, pluginsDirectoryPath);
pluginsDirectoryPath = System.IO.Path.GetFullPath(pluginsDirectoryPath);
if (System.IO.Directory.Exists(pluginsDirectoryPath) == false)
{
throw new CriticalException(
"The plugins directory path is not defined. Add Plugins parameter to configuration file.");
}
//An aggregate catalog that combines multiple catalogs
var catalog = new AggregateCatalog();
// Plgins only load from plugins directory for now
catalog.Catalogs.Add(new DirectoryCatalog(pluginsDirectoryPath));
//Create the CompositionContainer with the parts in the catalog
var container = new CompositionContainer(catalog);
//Fill the imports of this object
try
{
container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
throw new CriticalException("Unable to load authentication plugins", compositionException);
}
}
#endregion [ MEF Loading ]
以上所有代码都在同一个类中,现在我们需要在该类的构造函数中创建一个实例。
public ABCFacade(Ifacade iFacade)
{
LoadPlugin();
_iFacade = iFacade; // Make sure the class instance that you want to create in the child class must have a [Export] tag, like we did in above.
}
Export(typeof(IProvider))]
[ExportMetadata("ProviderName", "ABC")]
public class Plugin : IProvider
{
private readonly IFacade _iFacade;
[ImportingConstructor] // This tag will override the constructor.
public Plugin(IFacade iFacade)
{
_iFacade = iFacade;
}
}