4

我在一个新的 ASP.NET MVC4 项目中使用来自MEF 的用于 Web 和 Windows 应用商店应用 NuGet 包的 System.Composition 命名空间。

我已经读到在 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();
}

扩展元数据.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();
            }                   
        }           
    }
}

我想我在这里遗漏了一些非常重要的东西。基本上我想懒惰地导入所有扩展,检查它们的元数据,如果满足条件,让那个扩展做一些事情。

非常感谢您的反馈或任何涵盖我的场景的示例代码/教程的链接。

非常感谢!

4

1 回答 1

3

我想在阅读了这个 SO question之后我已经解决了。

我创建了一个元数据属性:

[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();
                }
            }
        }
    }
}

这似乎可以解决问题,但我仍然会对任何关于最佳实践、性能问题等的反馈感兴趣。

谢谢!

于 2012-12-18T06:35:45.420 回答