Question

I'm a complete beginner here, so this might be a really obvious question, I just can't quite seem to understand or find an answer. I've read the MSDN example and most of it makes complete sense.

In the example, they define the following interfaces and give example usage like this;

public interface IOperation
{
    int Operate(int left, int right);
}

public interface IOperationData
{
    char Symbol { get; }
}

[Export(typeof(IOperation))]
[ExportMetadata("Symbol", '+')]
public class Add : IOperation
{
    public int Operate(int left, int right)
    {
        return left + right;
    }
}

I think I must be misunderstanding something here.

  • What's the point of IOperationData and ExportMetadata ?
  • Why can't I just drop them both and add char Symbol {get;} to IOperation ?

Then I could just use Add.Value.Symbol instead of Add.Metadata.Smybol. I guess that's not really a huge change, but it does mean I don't need ExportMetadata. What's the difference between Value and Metadata and why does the example use them like it does? Is Metadata for properties and Value for methods? It doesn't seem very well explained to me.

Was it helpful?

Solution

MEF allows composable parts to provide their metadata. Metadata here is a set of statically-known properties, which is typical for part type, not for the type instance.

Suppose you're building a GUI for calculator in the given example.
Each operation is a plugin here, which being loaded via MEF container. You don't want to instantiate every plugin until user selection, but you want to build the panel with buttons, where each button holds an operation symbol.

That's why you need to use metadata instead of adding char Symbol {get;} to IOperation:

  • you can access metadata without instantiation of part (this could be expensive);
  • the metadata belongs to the composable part, and every instance of that part should have the same metadata (although calculator example isn't a good choice for understanding that fact).

You're describing metadata interface IOperationData and applying ExportMetadata attribute to the composable part definition. Then, at run-time, MEF looks at Add class, and dynamically builds IOperationData implementation. The instance of that implementation being initialized with values, provided in ExportMetadata. And, finally, you can access the values of IOperationData implementation with Add.Metadata.Smybol later in host application.

UPDATE. ExportMetadata allows you to add multiple metadata values, but it is often more convenient to add metadata, using custom attribute, which is inherited from ExportAttribute:

public interface IMyPlugin {}
public interface IMyMetadata
{
    int Value1 { get; }
    string Value2 { get; }
}

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class MyExportAttribute : ExportAttribute, IMyMetadata
{
    public MyExportAttribute(int value1, string value2)
        : base(typeof(IMyPlugin))
    {
        Value1 = value1;
        Value2 = value2;
    }

    public int Value1 { get; private set; }
    public string Value2 { get; private set; }
}

Usage:

   [MyExport(1, "Orange")] 
   public class MyPlugin : IMyPlugin {}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top