MEF和基于元数据的导出

本文关键字:元数据 MEF | 更新日期: 2023-09-27 18:10:34

好的,我很确定这是非常明显的东西,但我没有找到它。

我试图从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

在工厂

var controllerExport = _container.GetExports<IController, ControllerMetadataAttribute>().
                                    Where(exp => exp.Metadata.Name.Equals(controllerName) && exp.Metadata.Subdomain.Equals(subdomain)).
                                    FirstOrDefault();

和我得到

类型'ControllerMetadataAttribute'提供的不是一个有效的元数据视图。'

为什么无效?它有MetaDataAttribute和所有?

MEF和基于元数据的导出

在您的示例中,您使用的是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();

更进一步,您可以将ExportExportMetadata属性合并为单个属性:

[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 { }

在我的情况下,错误是在模型内,我需要删除set;从属性和工作:

public interface INamedMetadata
{
    string ValidationRule { get; }
}