20

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();
    }
  }
}
Luke Bennett
  • 32,786
  • 3
  • 30
  • 57
  • I think your assumption is correct - it seems a little outside of the problem MEF is intended to solve. – GraemeF Nov 20 '09 at 13:25

3 Answers3

31

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
  • 4,284
  • 1
  • 22
  • 21
  • It seems that the OrderingCollection sample is no longer available. – tofutim Mar 10 '15 at 17:11
  • I think a derivative of `OrderingCollection` can be found in Sony Authoring Tools Framework source, [here](https://github.com/SonyWWS/ATF/blob/master/Framework/Atf.Gui/Collections/AdaptingCollection.cs). – tomsseisums Aug 10 '15 at 14:21
  • 1
    I notice that codepaste is gone, so I've places it here for whoever needs it: https://gist.github.com/mika76/8cab4c16e420da4fe6e069071415ca70 – Mladen Mihajlovic Nov 01 '19 at 09:42
6

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
  • 8,463
  • 1
  • 32
  • 34
  • 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 Dec 19 '09 at 10:31
  • It's ok, Wes based his version on mine :-) – Glenn Block Dec 21 '09 at 21:59
1

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
  • 11,327
  • 5
  • 52
  • 76