4

我对 MEF 比较陌生,所以我不完全了解这些功能。我正在尝试实现类似于 Unity 的 InjectionMember 的功能。

假设我有一个导入 MEF 部件的类。为了简单起见,我们以下面的类作为导出部分的示例。

[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class Logger {

    public string Category {
        get;
        set;
    }

    public void Write(string text) {
    }

}

public class MyViewModel {

    [Import]
    public Logger Log {
        get;
        set;
    }

}

现在我想弄清楚是否可以在导入时为 Category 属性指定一个值。就像是:

public class MyViewModel {

    [MyImportAttribute(Category="MyCategory")]
    public Logger Log {
        get;
        set;
    }

}

public class MyOtherViewModel {

    [MyImportAttribute(Category="MyOtherCategory")]
    public Logger Log {
        get;
        set;
    }

}

目前,我正在做的是实现 IPartImportsSatisfiedNotification 并在代码中设置类别。但显然我宁愿把所有东西都整齐地放在一个地方。

4

2 回答 2

6

MEF 编程指南中,阅读有关导出和元数据的部分。它显示了如何通过使用ExportMetadata属性或定义您自己的自定义导出属性来在导出的部件上添加元数据。

然后,您可以定义这样的ILoggerMetadata接口:

public interface ILoggerMetadata
{
    string Catagory { get; }
}

并执行ImportManyaIEnumerable<Lazy<ILogger,ILoggerMetadata>>并选择您想要的代码,如下所示:

private ILogger fooLogger;

[ImportMany]
public IEnumerable<Lazy<ILogger,ILoggerMetadata>> Loggers
{
    set
    {
        this.fooLogger = value.First(x => x.Metadata.Catagory == "foo").Value;
    }
}

我同意将元数据约束直接放在导入属性中会更好,但目前在开箱即用的 MEF 中这是不可能的。(可能可以扩展 MEF 来执行此操作。)

另一种方法是从 派生IFooLogger接口ILogger,并在导入和导出中使用它。这很简单,并且与将约束放在导入中具有基本相同的效果。但是,如果您有多个元数据属性和/或许多可能的值,则此方法不起作用。

编辑:我巧妙地误解了你的问题;我认为这是关于限制导入,而不是使用一些额外的参数配置导入的对象。

我认为Kathleen Dollard最近的这篇文章是关于同样的问题。此外,在这篇关于组件关系的文章中,Nicholas Blumhardt 将这种“参数化”关系建模为注入Func<X,Y>(或Func<ILogger,string>在您的情况下)。

您可以在 MEF 中通过将[Export(typeof(Func<ILogger,string>))]属性直接放在方法上来执行相同的操作。或者,如果您需要一个不那么模糊的合同,您可以定义一个ILoggerFactory接口并导入/导出:

public ILoggerFactory
{
    ILogger Create(string category);
}

最后,您仍然必须在代码中调用工厂。

于 2010-04-15T09:35:19.750 回答
3

在深入研究 MEF 之后,似乎没有办法以声明方式执行此操作。虽然您可以派生自己的导出属性,但似乎没有任何机制可以以任何有意义的方式派生导入属性。

但不是实现 IPartImportsSatisfiedNotification,我能做的(现在看起来很明显)是在 setter 中设置类别。我必须放弃自动属性,但这就是生活。

public class MyViewModel {

    private Logger log;

    [Import]
    public Logger Log {
        get { return log; }
        set {
            log = value;
            log.Category = "MyCategory";
        }
    }

}
于 2010-04-15T14:09:20.883 回答