MEF GetExportedValue with metadata
I want to use MEF as a DI for my project. I have 1 project and every classes that should be composed resides there (they share one interface). Now I want to create one of them by specifiyng a metadata v开发者_如何学JAVAalue. Here's the definitions:
public interface IGatewayResponseReader
{
object Read(string msg);
}
[Export(typeof(IGatewayResponseReader))]
[ExportMetadata(G3Reader.META_KEY, "value1")]
public class TestReader1 : IGatewayResponseReader
{
...
}
[Export(typeof(IGatewayResponseReader))]
[ExportMetadata(G3Reader.META_KEY, "value2")]
public class TestReader2 : IGatewayResponseReader
{
...
}
Now I want to create an instance of TestReader1 through MEF, but I don't know how to filter by metadata through CompositionContainer. I want something like
Container.GetExportedValue<IGatewayResponseReader>();
But to specify the metadata to choose which class instance to create.
Your help is much appreciated.
Thanks.
The answer provied by @Dmitry Ornatsky is correct, but the preferred way of providing export metadata is to use strongly-typed metadata using a custom export attribute:
public interface IGatewayResponseReaderMetadata
{
string Key { get; }
}
[MetadataAttribute]
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Property )]
public class GatewayResponseReaderExportAttribute : ExportAttribute
{
public GatewayResponseReaderExportAttribute( string key )
: base( typeof( IGatewayResponseReader ) )
{
this.Key = key;
}
public string Key { get; set; }
}
[GatewayResponseReaderExport("value1")]
public class TestReader1 : IGatewayResponseReader
{
}
The code to look up an import can then be made type-safe. Note that it's a good idea to check if import is not null before accessing the Value
property:
class Program
{
[ImportMany]
private List<Lazy<IGatewayResponseReader, IGatewayResponseReaderMetadata>> _readers;
static void Main( string[] args )
{
CompositionContainer container = new CompositionContainer( new AssemblyCatalog( Assembly.GetExecutingAssembly() ) );
Program program = new Program();
container.SatisfyImportsOnce( program );
var reader = program._readers.FirstOrDefault( r => r.Metadata.Key == "value1" );
if ( reader != null )
reader.Value.Read( ... );
}
}
class Program
{
[ImportMany]
private List<Lazy<IGatewayResponseReader, IDictionary<string, object>>> _readers;
static void Main(string[] args)
{
CompositionContainer container = new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
Program program = new Program();
container.SatisfyImportsOnce(program);
var result = program._readers.Where(r =>
r.Metadata.ContainsKey(G3Reader.META_KEY) && (string)r.Metadata[G3Reader.META_KEY] == "value1")
.First().Value;
}
}
精彩评论