【问题标题】:Difference between Import and ImportingConstructor attributes in MEF with proper examples?MEF 中的 Import 和 ImportingConstructor 属性之间的区别以及适当的示例?
【发布时间】:2017-07-28 11:06:15
【问题描述】:

任何人都可以通过相关示例以及何时使用 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 属性吗?

如果有人能用更好的例子来解释,那就太好了。

任何帮助将不胜感激。 谢谢

【问题讨论】:

    标签: c# .net mef


    【解决方案1】:

    导入构造函数

    在示例代码中导入/导出部件的方式,如果 MyMainClass 正在组合,则调用隐式无参数构造函数,然后MySimpleCalculator 的实例分配给 @987654324 @字段。

    现在假设您希望拥有一个只读字段/一个仅获取属性,或者需要在构造函数中访问 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
        }
    }
    

    现在构造函数的参数被隐式导入并满足相应的导出。

    允许默认

    如果您 [Import] 某些内容,则该内容必须可用,否则合成失败。

    如果你 [Import(AllowDefault = true)] 某些东西,如果没有相应的导出,合成不会失败,但你会得到 null/false/0 作为导入值。

    顺便说一句:抱歉有点讽刺,但答案也可以是RTFM

    【讨论】:

      【解决方案2】:

      在您的应用程序中,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;
      }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-19
        • 2013-03-16
        • 2017-06-30
        • 1970-01-01
        • 1970-01-01
        • 2021-05-28
        • 1970-01-01
        • 2019-06-06
        相关资源
        最近更新 更多