MEF поддерживает экспорт пользовательских метаданных для сопровождения ваших экспортируемых типов. Что вам нужно сделать, это сначала определить интерфейс, который MEF будет использовать для создания прокси-объекта, содержащего ваши метаданные. В вашем примере вам, вероятно, понадобится уникальное имя для каждого экспорта, поэтому мы можем определить:
public interface INameMetadata
{
string Name { get; }
}
В таком случае вам необходимо назначить метаданные для каждого экспорта, для которого он требуется:
[Export(typeof(IMessageSender)), ExportMetadata("Name", "EmailSender1")]
public class EmailSender : IMessageSender
{
public void Send(string message)
{
Console.WriteLine(message);
}
}
Что MEF сделает, так это сгенерирует проект с реализацией вашего интерфейса, INameMetadata
с использованием значения, хранящегося в атрибуте ExportMetadata("Name", "EmailSender1")
.
После того, как вы это сделаете, вы можете сделать небольшую фильтрацию, поэтому переопределите ваш [Import]
примерно так:
[ImportMany]
public IEnumerable<Lazy<IMessageSender, INameMetadata>> Senders { get; set; }
MEF создаст перечислимые Lazy<T, TMetadata>
экземпляры, которые поддерживают отложенное создание экземпляра вашего типа экземпляра. Мы можем запросить как:
public IMessageSender GetMessageSender(string name)
{
return Senders
.Where(l => l.Metadata.Name.Equals(name))
.Select(l => l.Value)
.FirstOrDefault();
}
Выполнение этого с аргументом "EmailSender1"
для параметра name
приведет к возвращению нашего экземпляра EmailSender
. Важно отметить, как мы выбрали конкретный экземпляр для использования на основе запроса метаданных, связанных с типом.
Вы можете пойти еще дальше и объединить атрибуты Export
и ExportMetadata
в один атрибут, такой как:
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false), MetadataAttribute]
public class ExportMessageSenderAttribute : ExportAttribute, INameMetadata
{
public ExportMessageSenderAttribute(string name)
: base(typeof(IMessageSender))
{
Name = name;
}
public string Name { get; private set; }
}
Это позволяет нам использовать один атрибут для экспорта типа, в то же время предоставляя дополнительные метаданные:
[ExportMessageSender("EmailSender2")]
public class EmailSender : IMessageSender
{
public void Send(string message)
{
Console.WriteLine(message);
}
}
Очевидно, что запрос этого способа представляет вам проектное решение. Использование Lazy<T, TMetadata>
экземпляров означает, что вы сможете отложить создание экземпляра экземпляра, но это означает, что для каждого ленивого может быть создан только один экземпляр. Вариант Silverlight среды MEF также поддерживает тип ExportFactory<T, TMetadata>
, который позволяет вам каждый раз показывать новые экземпляры T
, в то же время предоставляя вам механизм с богатыми метаданными.