添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Difference between Import and ImportingConstructor attributes in MEF with proper examples?

Ask Question

Can anyone help me with Import and ImportingConstructor attributes in MEF with relevant examples and when to use ? what is the use of [Import(AllowDefault = true)] ?

From my understanding of MEF:

Export attribute is defined on Class of type T where T is interface and to create a instance of that class Import attribute should be defined on the reference variable like below

[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;

If Multiple Exports of type T are defined in a given assembly then we can use ImportMany attribute.

So now can anyone explain when to use Import and ImportingConstructor and also AllowDefault attribute in the constructor ?

It would be great if someone can explain with better examples.

Any help would be appreciated. Thanks

ImportingConstructor

The way you Import/Export parts in your sample code, if MyMainClass is getting composed, the implicit parameterless constructor is called, then an instance of MySimpleCalculator is assigned to the calculator field.

Now let's say you rather want to have a readonly field/a get-only property, or otherwise need to access the ICalculator in the constructor, you need to have it passed to the constructor rather than later on assigned to the field:

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

Now the argument(s) to the constructor are implicitly imported and satisfied with a corresponding export.

AllowDefault

If you [Import] something, that something must be available or composition fails.

If you [Import(AllowDefault = true)] something, composition wont' fail if there's no corresponding export, but you get null/false/0 as imported value.

There are three basic parts to MEF in your application. If we use a laptop analogy, we can visualize these three parts as the USB port on the laptop, an external hard drive with a USB connector, and the hand that plugs the USB connector into the port. In MEF terms, the port is defined as an [Import] statement. This statement is placed above a property to tell the system that something gets plugged in here. The USB cable is defined as an [Export] statement. This statement is placed above a class, method, or property to indicate that this is an item to be plugged in somewhere. An application could (and probably will) have a lot of these exports and imports. The job of the third piece is to figure out which ports we have and thus which cables we need to plug into them. This is the job of the CompositionContainer. It acts like the hand, plugging in the cables that match up to the appropriate ports. Those cables that don’t match up with a port are ignored.

[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
container.ComposeParts(this);
catch (CompositionException compositionException)
throw new CriticalException("Unable to load authentication plugins", compositionException);
#endregion [ MEF Loading ]

All the above code is in the same class, now we need to create an instance in the constructor of that class.

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;
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.