Providing Metadata to your MEF exports

Many months ago I created a post on how to get started with MEF.  Ever since then I have been meaning to get this post (and others) about about how to get up and running quickly with MEF.

In this post will demonstrate how to provide Metadata (custom values which can help provide context) information to your Exported item.  Why should you care about Metedata?  Below is a great reason from the MEF site on codeplex

Declaring Exports explained the basics of parts exporting services and values. In some cases it’s necessary to associate information with exports for a variety of reasons. Commonly it’s used to explain about the capabilities of an specific implementation of a common contract. This is useful to allow imports to either constraint the export that can satisfy it, or to import all available implementations at the time and check their capabilities in runtime before using the export.

Before we get rolling:

What I am going to show in this post is how to create a custom Export Attribute.  It is possible to expose Meta via the build in ExportAttribute, but the built in mechanism has a few short comings:

  1. Not discoverable
  2. Not strongly typed
  3. Compiler cannot validate the data content

Lets get rolling:

Pre-Step 1: Taking a look at the Class which we will mark as a Export

    public interface IPlugin
    {
        string PluginAction();
    }

    [Export(typeof(IPlugin))]
    public class DefaultPlugin : IPlugin 
    {
        public string PluginAction()
        {
            return "This is the default plugin";
        }
    }


 

Step 1: Defining the interface which will represent your

In order to create discoverable Metadata you will first want to create an interface which will represent your metadata.  Below is my interface.

    public interface IPluginMetaData
    {
        string Name { get; }
        string Version { get; } 
    }


 

We will later use this interface when we define and use our custom Export Attribute.  The main reason for creating this attribute is now the compiler has a hard wired way to know exactly what type of data is being exposed in your Metadaa

Step 2: Defining your custom ExportAttribute Attribute

Now that we created our interface to give us strong typing and discoverability we need to create a custom attribute which will allows the MEF engine to know we have Metadata to expose

    [MetadataAttribute]
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class PluginMetadataAttribute : ExportAttribute
    {
        public PluginMetadataAttribute( string name, string version)
            : base(typeof(IPluginMetaData))
        {
            Name = name;
            Version = version;
        }

        public string Name { get; set; }
        public string Version { get; set; }
    }


 

When looking at the code above there are 3 things to pay close attention to

  1. You need to make a call into the base constructor of the ExportAttribute and provide it the type of your interface which defines your Metadata
  2. You need to mark your attribute with the [MetadataAttribute] (which is part of MEF)
  3. You need to mark the usage type of your attribute.  I am not 100% why this is needed (Glenn, you out there with an answer???)

Step 3: Providing your Metdata to your Exported Class

    [Export(typeof(IPlugin))]
    [PluginMetadata("Default", "1.0.0.0")]
    public class DefaultPlugin : IPlugin 
    {
        public string PluginAction()
        {
            return "This is the default plugin";
        }
    }


 

The code above is the same as the code we saw in pre-step 1, but this time we have marked the class with our custom Metadata attribute.  We have now officially provided our Metadata to our Export…. But how do we get this information out of MEF?

Step 4: Setting up your [ImportMany] to use the Metadata

If you are using an ImportMany (this should also work on an Import, but I have never tried) most likely you are pushing your Exports into a IList or IEnumerable.  If this is the case, your changes are pretty minor.  Below is what you need to do in order to have your Metadata loaded.

[ImportMany(typeof(IPlugin), AllowRecomposition = true)]
private IList<Lazy<IPlugin, IPluginMetaData>> _loadedIPlugins = new List<Lazy<IPlugin, IPluginMetaData>>();


 

If you have not seen the Lazy keyword, you are not alone.  This is new to .Net 4 and this provides Lazy initialization support to the framework.  (part of the System namespace).  One key thing to understand here though is that the Lazy keyword out the box is only Lazy<T>, but the Lazy we are using is Lazy<T, M>.  This extended version of Lazy lives in the MEF assemblies (System.ComponentModel.Composition) and will need to be referenced to use.

Step 5: Using the Metadata

Once you have the Export loaded into your container (which by the way does not need to change to have this work) you can access your container by selecting the .Metadata property on your instance of the export.  The image below shows it in action.

image

As you can see, exposing and using Metadata via MEF is a snap. 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值