MEF和基于元数据的导出

Ing*_*als 11 c# mef metadata export

好吧我很确定这是一件令人眼花缭乱的事情,但我找不到它.

我正在尝试根据它的元数据从MEF容器中导出一个对象.

我在这样的教程中看到过这个:

http://blog.maartenballiauw.be/post/2009/04/21/ASPNET-MVC-and-the-Managed-Extensibility-Framework-%28MEF%29.aspx

但是,我的导出没有为此工作所必需的元数据属性.那可能是什么问题?

[Export(typeof(IController))]
[ExportMetadata("controllerName","Home")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller{}
Run Code Online (Sandbox Code Playgroud)

然后再次

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.
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道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; }
}
Run Code Online (Sandbox Code Playgroud)

然后在每个控制器中

[Export(typeof(IController))]
[ControllerMetadata("Home", "")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : SubdomainManagedController
Run Code Online (Sandbox Code Playgroud)

在工厂里

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

而且我正在

提供的Type"ControllerMetadataAttribute"不是有效的元数据视图

它怎么没有效.它有MetaDataAttribute和所有?

Mat*_*ott 19

在您的示例中,您使用的是GetExports<T>,而不是GetExports<T,TMetadata>.在一个简单的例子,你可以使用GetExports<IController, IDictionary<string, object>>,这样可以让你查询,但这样做的更好的方式是创建一个自定义的元数据合同:

public interface INameMetadata
{
    string Name { get; }
}
Run Code Online (Sandbox Code Playgroud)

您可以将其用作:

[Export(typeof(IController))]
[ExportMetadata("Name", "Home")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller { }
Run Code Online (Sandbox Code Playgroud)

然后将导入更改为:

var controller = _container.GetExports<IController, INameMetadata>()
                           .Where(e => e.Metadata.Name.Equals(controllerName))
                           .Select(e => e.Value)
                           .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

更进一步,您可以将您的属性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; }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以将其用于导出:

[ExportController("Home"), PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller { }
Run Code Online (Sandbox Code Playgroud)

  • 您需要将`GetExports <T,TMetadata>`调用从`GetExports <IController,ControllerMetadataAttribute>`更改为`GetExports <IController,IControllerMetadata>`.此外,您不需要额外的`[Export(typeof(IController))]`,因为导出由`[ControllerMetadata("Home","")]提供. (2认同)