tags:

views:

498

answers:

3

MEF allows you to import multiple parts via the use of the ImportMany attribute. How does it determine the order in which it retrieves the relevant exports and adds them to the enumerable you are populating? For example, how would I import multiple IRules that had to fire in a particular order? The only way I can think of is to have an OrderValue property in IRule and sort manually:

public class Engine
{
  [ImportMany]
  public IEnumerable<IRule> Rules { get; set; }

  public void Run()
  {
    // ...
    // Initialise MEF
    // ...

    //
    // Do I need to manually order Rules here?
    //

    foreach (IRule rule in Rules)
    {
      // Must execute in a specific order
      rule.Execute();
    }
  }
}
+1  A: 

You could have the rules import each other in order (using the Decorator pattern), but then each rule will need to know about the specific rule that precedes it, which probably isn't what you want.

MEF is there to help you discover the parts, what you do with them afterwards is up to you. If you want to sort the parts then go ahead, there's nothing wrong with that!

GraemeF
This confirmed what I expected, thanks.
Luke Bennett
+7  A: 

By default MEF does not guarantee any order of the exports that get imported. However in MEF you can do some ordering by using some metadata and a custom collection. For example you can do something like:

public interface IRule { }

[Export(typeof(IRule))]
[ExportMetadata("Order", 1)]
public class Rule1 : IRule { }

[Export(typeof(IRule))]
[ExportMetadata("Order", 2)]
public class Rule2 : IRule { }

public interface IOrderMetadata
{
    [DefaultValue(Int32.MaxValue)]
    int Order { get; }
}

public class Engine
{
    public Engine()
    {
        Rules = new OrderingCollection<IRule, IOrderMetadata>(
                           lazyRule => lazyRule.Metadata.Order);
    }

    [ImportMany]
    public OrderingCollection<IRule, IOrderMetadata> Rules { get; set; }
}

Then you will have a set of rules that are ordered by the metadata. You can find the OrderingCollection sample at http://codepaste.net/ktdgoh.

Wes Haggard
Thanks! Have changed my accepted answer to yours.
Luke Bennett
Great solution!
Kilhoffer
+4  A: 

Hi

The best way to achieve this ordering in MEF is to utilize our metadata facilities. You can attach your own metadata to exports which you can use for ordering and filtering. Metadata also allows you to delay instantiation of parts until they are actually needed. Additionally you can create custom Export attributes which provide a nice clean way of providing the metadata.

Check this link for information on how to define metadata and custom exports: link text

You may also find this thread on our MEF forums useful. Within you'll find a discussion about an AdaptingCollection approach which lets you use a custom collection which applies a metadata filter / order.

HTH Glenn

Glenn Block
Thanks Glenn, in the end I took a different approach but I'll certainly bear this in mind for next time. I would accept your answer but as Wes got in just before with a similar response I think it's probably fairer to accept his.
Luke Bennett
It's ok, Wes based his version on mine :-)
Glenn Block