Custom Import Attribute

Mar 11, 2011 at 12:50 PM

Hi,

I'm learning MEF now after I've learn and play a little with google guice. There are a lot of resemblance which ensure me both are great frameworks.

One thing that I not so happy about with MEF attribute model is that anything that is not type based match (export give IService and import need IService) is based on magic strings. Putting those strings in constant does not solve the problem.

Another problem is that .NET already has great mechanism for metadata - that is attributes Microsoft go long way to create specific mechanism for attaching metadata to export attributes.

Inherit from ExportAttribute and put the extra metadata in it is great but it is not complete because we don't have a way to import based on that metadata yet.

Import all the possible exports by type and only then filter them according to metadata is good but it not what I'm looking for.

 

In google guice you can define custom attribute (annotation in Java) to use on the export and use that same custom attribute on the import - guice use the custom attribute as extra metadata to match the export to the import.

For example, if I want to use MEF to export several configuration properties - all of type int: one represent the port in which my server runs and the other the number of seconds to poll the server:

  public class MyConfig {
    [Export("Port")]
    public int Port { get { return 33; } }

    [Export("PollInterval")]
    public int PollInterval { get { return 105; } }
  }

If I not want to import the port property on a ctor I have to use the magic string again like so:

  public class MyClient {
    private readonly int serverPort;

    [ImportingConstructor]
    public MyClient([Import("Port")] int serverPort) {
      this.serverPort = serverPort;
    }
  }

Now, imagine we could take advantage of the built in attributes of .NET like so:

  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
  sealed class PortAttribute : Attribute {
  }

  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
  sealed class PollIntervalAttribute : Attribute {
  }

  public class MyConfig {
    [Export, Port]
    public int Port { get { return 33; } }

    [Export, PollInterval]
    public int PollInterval { get { return 105; } }
  }

and have them import like so:

  public class MyClient {
    private readonly int serverPort;

    [ImportingConstructor]
    public MyClient([Import, Port] int serverPort) {
      this.serverPort = serverPort;
    }
  }

Off course we can then use the properties of the custom attributes for even more advanced senario.

Is that a good idea or totally wrong?

What need to happen in order for this kind of metadata use to work?

 

Thank you,

Ido.

Apr 8, 2011 at 10:40 PM

Can someone please comment on this.

Thank you,

Ido.