OK I'm pretty sure this is something blindingly obvious but I'm not finding it.
I'm trying to export a object from MEF container based on it's Metadata.
I've seen this done in tutorials like this one:
http://blog.maartenballiauw.be/post/2009/04/21/ASPNET-MVC-and-the-Managed-Extensibility-Framework-%28MEF%29.aspx
However my export doesn't have the Metadata property that is necessary for this to work. What could be the problem there?
[Export(typeof(IController))]
[ExportMetadata("controllerName","Home")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller{}
and again
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.
}
}
I understand that the GetExports returns a collection of Lazy that do of course not have the Metadata property but it's assumed in most tutorials I look through.
How do I do this correctly?
This is what I did:
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; }
}
Then in each controller
[Export(typeof(IController))]
[ControllerMetadata("Home", "")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : SubdomainManagedController
and in the factory
var controllerExport = _container.GetExports<IController, ControllerMetadataAttribute>().
Where(exp => exp.Metadata.Name.Equals(controllerName) && exp.Metadata.Subdomain.Equals(subdomain)).
FirstOrDefault();
and I'm getting
The Type 'ControllerMetadataAttribute' supplied is not a valid Metadata View.`
How is it not valid. It has the MetaDataAttribute and all?
Managed Extensibility Framework (MEF) - . NET Framework | Microsoft Learn. This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
You can use MEF in your client applications, whether they use Windows Forms, WPF, or any other technology, or in server applications that use ASP.NET. MEF has been ported as Microsoft. Composition to . NET Core as well but partially.
By using [ImportingConstructor] , you allow one class that serves as an export to import its dependencies. This dramatically simplifies the architecture, as you can decouple the dependencies of a concrete object from its implementation.
In your example, you're using GetExports<T>
, instead of GetExports<T,TMetadata>
. In a simple example, you can use GetExports<IController, IDictionary<string, object>>
, which would allow you to query, but a nicer way of doing it is to create a custom metadata contract:
public interface INameMetadata
{
string Name { get; }
}
Which you can then use as:
[Export(typeof(IController))]
[ExportMetadata("Name", "Home")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller { }
And then change your import to:
var controller = _container.GetExports<IController, INameMetadata>()
.Where(e => e.Metadata.Name.Equals(controllerName))
.Select(e => e.Value)
.FirstOrDefault();
Going one step further, you could combine your Export
and ExportMetadata
attributes into a single attribute:
[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; }
}
Now, you can use that with your export:
[ExportController("Home"), PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller { }
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