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 value. 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( ... );
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With