Метаданные со строгой типизацией в MEF2 (System.Composition)
Я использую пространство имен System.Composition из MEF для пакета NuGet для веб-приложений и приложений Магазина Windows в новом проекте ASP.NET MVC4.
Я читал, что в MEF2 вы больше не используете Lazy<IExtension, IExtensionMetadata>
, но теперь вы должны предоставить конкретный тип для представления метаданных (и, возможно, использовать ExportFactory<> вместо Lazy<>?).
Однако я не могу найти никаких примеров того, как все это должно работать - лишь несколько упоминаний об использовании конкретного типа вместо интерфейса.
Я пробовал несколько вещей, но продолжаю получать следующую ошибку - "Экспорт метаданных для" AccountID "отсутствует, и значение по умолчанию не было предоставлено".
Мой код...
Создание контейнера (в папке Global.asax или App_Start):
// Get assemblies that will be providing imports and exports
var assemblies = GetAssemblies();
// Get conventions that will be used to find imports and exports
var conventions = GetConventions();
var container = new ContainerConfiguration().WithAssemblies(assemblies, conventions).CreateContainer();
// Create and apply a MefControllerFactory so controllers can be composed
ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(container));
Метод GetConventions():
private static ConventionBuilder GetConventions()
{
var conventionBuilder = new ConventionBuilder();
conventionBuilder.ForTypesDerivedFrom<IController>().Export();
conventionBuilder.ForTypesDerivedFrom<IExtension>().Export<IExtension>();
conventionBuilder.ForTypesMatching(t => t.Namespace != null && t.Namespace.EndsWith(".Parts")).Export().ExportInterfaces();
return conventionBuilder;
}
IExtension.cs:
public interface IExtension
{
void DoWork();
}
ExtensionMetadata.cs:
public class ExtensionMetadata
{
public int AccountID { get; set; }
}
ExtensionA.cs (такой же, как ExtensionB.cs):
public void DoWork()
{
System.Diagnostics.Debug.WriteLine("ExtensionA doing work..");
}
ExtensionManager.cs:
public class ExtensionManager
{
private IEnumerable<ExportFactory<IExtension, ExtensionMetadata>> _extensions;
public ExtensionManager(IEnumerable<ExportFactory<IExtension, ExtensionMetadata>> extensions)
{
_extensions = extensions;
}
public void DoWork(int accountID)
{
foreach (var extension in _extensions)
{
if (extension.Metadata.AccountID == accountID)
{
extension.DoWork();
}
}
}
}
Я думаю, что мне здесь чего-то не хватает. По сути, я хочу лениво импортировать все расширения, проверить их метаданные и, если условие выполнено, сделать это расширение.
Буду очень признателен за ваши отзывы или любые ссылки на примеры кода / учебники, которые охватывают мой сценарий.
Большое спасибо!
1 ответ
Я думаю, что я решил это после прочтения этого ТАКОГО вопроса.
Я создал атрибут метаданных:
[MetadataAttribute]
public class ExtensionMetadataAttribute : ExportAttribute, IExtensionMetadata
{
public int AccountID { get; set; }
public ExtensionMetadataAttribute(int accountID) : base(typeof (IExtension))
{
AccountID = accountID;
}
}
Затем изменил ExtensionA.cs:
[ExtensionMetadata(1)]
public class ExtensionA : IExtension
{
public void DoWork()
{
System.Diagnostics.Debug.WriteLine("ExtensionA doing work..");
}
}
И теперь ExtensionManager.cs выглядит так:
public class ExtensionManager : IExtensionManager
{
private readonly IEnumerable<ExportFactory<IExtension, ExtensionMetadata>> _extensions;
public ExtensionManager(IEnumerable<ExportFactory<IExtension, ExtensionMetadata>> extensions)
{
_extensions = extensions;
}
public void DoWork(int accountID)
{
foreach (var extension in _extensions)
{
if (extension.Metadata.AccountID == accountID)
{
using (var foo = extension.CreateExport())
{
foo.Value.DoWork();
}
}
}
}
}
Это, кажется, делает свое дело, но я все еще был бы заинтересован в любой обратной связи относительно лучших практик, проблем с производительностью и т. Д.
Спасибо!