DCSIMG
MEF for Beginner (Metadata) - part 8 - Bnaya Eshet

Bnaya Eshet

Disclaimer

MEF for Beginner (Metadata) - part 8

MEF extensibility metadata MEF for Beginner (Metadata) - part 8

 

this is the 8th post of the MEF for Beginner series, the series TOC is available here.

 

this post will focus on the basics of MEF metadata capabilities,

the next post discuss the ability of multiple metadata decorations.

 

What is Metadata?

metadata is piece of compile-time information that can be attached to exported part.

  • metadata is adding peripheral information to the part,
    (metadata information may define which operation system supported by the plug-in).
  • metadata can be read before the instantiation of the part.

 

Typed metadata

MEF support both typed and non typed metadata, as is the case in other .net component

the best practice suggest using the typed metadata paradigm.

(our series will focus on the best practice of type metadata).

 

Which steps is needed for working with typed metadata?

the steps is needed is:

  • define the metadata (attribute)
  • decorate the exported part
  • define the metadata view contract
  • add the metadata view contract into the import signature

 

how to define typed metadata

defining metadata is very simple, all its take is to define attribute which

having public properties and is decorated with the [MetadataAttribute]

Code Snippet
  1. [MetadataAttribute]
  2. public class WeatherAttribute : Attribute
  3. {
  4.     public WeatherConditions Conditions { get; set; }
  5.     public int MinWindLimit { get; set; }
  6.     public int MaxWindLimit { get; set; }
  7. }

as you can see it is no different from any other .net attribute definition,

except of the decoration of [MetadataAttribute] in line 1.

 

Decorate the exported part
Code Snippet
  1. [Export(typeof(PluginBase))]
  2. [WeatherAttribute(MinWindLimit=0, MaxWindLimit=15,
  3.     Conditions = WeatherConditions.SnowyDays)]
  4. public class Rollerblading : PluginBase {... }

as you can see in line 2 the exported part is decorated with some metadata.

line 1 is decorating for the export (see the Improving the usability section for

learning how it can be more usable).

 

Define the metadata view contract

metadata view present the portion of the metadata that we want to interrogate,

(this contract can be class of interface and it can reflect all or part of the attribute public fields).

Code Snippet
  1. public interface IWeatherMetadata
  2. {
  3.     WeatherConditions Conditions { get; }
  4.     int MinWindLimit { get; }
  5.     int MaxWindLimit { get; }
  6. }

in the above case the metadata view contract is reflecting all of the public properties.

 

Import signature

the import definition should use Lazy type with 2 generics definitions,

the first definition for the plug-in contract, and the second for the metadata view contract.

Code Snippet
  1. [ImportMany]
  2. private IEnumerable<Lazy<PluginBase, IWeatherMetadata>> AllPlugIns { get; set; }

as you can see in line 2, MEF will create enumerable of lazy plug-ins which having typed weather metadata.

 

Inquiring the metadata

having the above import we may use Linq query (or any other technique) to filter the plug-in

portion that suite our needs (without having to instantiate the unneeded plug-ins).

Code Snippet
  1. public IEnumerable<PluginBase> SunnyActivities
  2. {
  3.     get
  4.     {
  5.         var plugins = from lazyPlugin in AllPlugIns
  6.                       let metadata = lazyPlugin.Metadata // typed metadata (IWeatherMetadata)
  7.                       where metadata.Conditions == WeatherConditions.Sunny
  8.                       select lazyPlugin.Value;
  9.         return plugins;
  10.     }
  11. }

the above sample is using the typed metadata to filter the sunny activities.

 

Behind the scenes

what is happening behind the scenes it that MEF is using reflection emit in order to construct

the typed metadata view.

 

Improving the usability

we can improve the usability of the previous sample by inheriting the ExportAttribute

(instead of Attribute), that way we can have single simple decoration for our export part.

Code Snippet
  1. [MetadataAttribute]
  2. [AttributeUsage (AttributeTargets.Class)]
  3. public class WeatherAttribute:ExportAttribute
  4. {
  5.     public WeatherAttribute(int minWindLimit, int maxWindLimit, WeatherConditions conditions) :
  6.         base(typeof(PluginBase))
  7.     {
  8.         Conditions = conditions;
  9.         MaxWindLimit = maxWindLimit;
  10.         MinWindLimit = minWindLimit;
  11.     }
  12.  
  13.     public WeatherConditions Conditions { get; private set; }
  14.     public int MinWindLimit { get; private set; }
  15.     public int MaxWindLimit { get; private set; }
  16. }

the above attribute define both typed metadata and export for the PluginBase type.

line 3: is inheriting the ExportAttribute.

 

the exported type decoration can be define using single simple attribute decoration.

Code Snippet
  1. [WeatherAttribute(0, 15, WeatherConditions.SnowyDays)]
  2. public class Rollerblading : PluginBase {...}

you are no longer having to use different attribute for export and metadata,

and as in this case the export type definition is handled by the attribute,

which enhance the consumer usability by having less area for errors.

 

Code sample

the code sample is demonstrating scenario were we want to present only plug-ins that suit

the current weather (the sample is using Google API for getting the NY weather).

you can download the sample for VS 2010 from here and for VS 2008 from here.

 

תגים של Technorati:‏ ,,,,,,

 

kick it on DotNetKicks.com


Comments

No Comments