Using metadata with MEF in Medium Trust
One of the awesome parts of MEF is that you can attach metadata to your objects. This allows you to use the new Lazy<T, TMetadata> object so you can inspect the meta data about an object without instantiating it. In order to attach metadata to an object, you need (should have) some entity that contains properties to support the meta data such as an interface (good tutorial site here ). For example, if you have a class of type MyObjectType and an interface to store metadata about the class of type IMyMetadata, you can then resolve/import Lazy<MyObjectType, IMyMetadata> which will expose a Metadata property of type IMyMetadata with the information filled in. You might already be able to tell that a bit of magic is happening behind the scenes since there is no concrete class for IMyMetadata but MEF has magically found a way to instantiate a class of type IMyMetadata and fill in the values. This is the problem area if you are running in Medium Trust, you will get a SecurityException stemming form the System.ComponentModel.Composition.MetadataViewGenerator. This same issue will occur when using Autofac to register metadata with the .WithMetadata extension method.
Solution
To work around this problem in Medium Trust, you’ll need to create a concrete class to store your metadata in instead of just referencing an interface. You’ll also need to ensure that the constructor of this class takes in one parameter of type IDictionary<string, object> and using this object you’ll need to manually do the heavy lifting of assigning the values to the properties of this class based on the values in the dictionary. Better yet, you can just make a base class that all your metadata classes can inherit from. In Umbraco v5, we’ve called this abstract class MetadataComposition just to keep inline with the naming conventions of the MEF namespace:
public abstract class MetadataComposition { /// <summary> /// constructor, sets all properties of this object based /// on the dictionary values /// </summary> /// <param name="obj"></param> protected MetadataComposition(IDictionary<string, object> obj) { var t = GetType(); var props = t.GetProperties(); foreach (var a in obj) { var p = props.Where(x => x.Name == a.Key).SingleOrDefault(); if (p != null) { p.SetValue(this, a.Value, null); } } } }
Hope this helps someone!