MEF и экспорт на основе метаданных
ОК. Я уверен, что это что-то ослепительно очевидное, но я не нахожу его.
Я пытаюсь экспортировать объект из контейнера MEF на основе его метаданных.
Я видел это в учебниках, подобных этому:
http://blog.maartenballiauw.be/post/2009/04/21/ASPNET-MVC-and-the-Managed-Extensibility-Framework-%28MEF%29.aspx
Однако мой экспорт не имеет свойства Metadata, которое необходимо для этого. В чем может быть проблема?
[Export(typeof(IController))]
[ExportMetadata("controllerName","Home")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller{}
и снова
public class MyControllerFactory : IControllerFactory
{
private readonly CompositionContainer _container;
public MyControllerFactory(CompositionContainer container)
{
_container = container;
}
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
var controllerExport = _container.GetExports<IController>().
Where(exp => exp.Metadata) //Here it doesn't have the Metadata property.
}
}
Я понимаю, что GetExports возвращает коллекцию Lazy, которая, конечно же, не имеет свойства Metadata, но она принимается в большинстве обучающих программ, которые я просматриваю.
Как это сделать правильно?
ИЗМЕНИТЬ
Это то, что я сделал:
public interface IControllerMetaData
{
string Name { get; }
string Subdomain { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class ControllerMetadataAttribute : ExportAttribute
{
public ControllerMetadataAttribute(string name, string subdomain)
: base(typeof(IControllerMetaData))
{
Name = name;
Subdomain = subdomain;
}
public string Name { get; set; }
public string Subdomain { get; set; }
}
Затем в каждом контроллере
[Export(typeof(IController))]
[ControllerMetadata("Home", "")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : SubdomainManagedController
и в factory
var controllerExport = _container.GetExports<IController, ControllerMetadataAttribute>().
Where(exp => exp.Metadata.Name.Equals(controllerName) && exp.Metadata.Subdomain.Equals(subdomain)).
FirstOrDefault();
и я получаю
Параметр Type 'ControllerMetadataAttribute' не является допустимым представлением метаданных.
Как это недействительно. У него есть MetaDataAttribute и все?
Ответы
Ответ 1
В вашем примере вы используете GetExports<T>
вместо GetExports<T,TMetadata>
. В простом примере вы можете использовать GetExports<IController, IDictionary<string, object>>
, который позволит вам запрашивать, но лучше всего это создать заказный контракт метаданных:
public interface INameMetadata
{
string Name { get; }
}
который затем можно использовать как:
[Export(typeof(IController))]
[ExportMetadata("Name", "Home")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller { }
И затем измените свой импорт на:
var controller = _container.GetExports<IController, INameMetadata>()
.Where(e => e.Metadata.Name.Equals(controllerName))
.Select(e => e.Value)
.FirstOrDefault();
Следуя еще одному шагу, вы можете объединить атрибуты Export
и ExportMetadata
в один атрибут:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false), MetadataAttribute]
public class ExportControllerAttribute : ExportAttribute, INameMetadata
{
public ExportControllerAttribute(string name)
: base(typeof(IController))
{
Name = name;
}
public string Name { get; private set; }
}
Теперь вы можете использовать это с вашим экспортом:
[ExportController("Home"), PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller { }