MEF:满足从组成部分导出使用和导出的部分

时间:2010-06-17 12:52:56

标签: c# .net silverlight mef composition

我在Silverlight 4中有以下场景:

我有通知服务

片段

[InheritedExport]
public interface INotificationsService : IObservable<ReceivedNotification>
{
    void IssueNotifications(IEnumerable<ClientIssuedNotification> notifications);
}

并实施此服务 段

[PartCreationPolicy(CreationPolicy.NonShared)]
public class ClientNotificationService : INotificationsService
{
    [Import]
    IPlugin Plugin { get; set; }
    ...
}

如何向MEF说明ClientNotificationService的Plugin属性必须由导入INotificationsService的导入类提供。

例如:

片段

public class Client
{
    [Export]
    IPlugin Current { get; set; }

    [Import]
    INotificationService NotificationService;
}

我怎么能说我希望MEF满足客户端类导出的IPlugin的ClientNotificationService.Plugin部分。

基本上我希望NotificationService接收导入类提供的唯一ID,无论何时创建并编写新类, 或者如果有替代方法,比如使用元数据来做这件事,我会很感激任何见解。我一直在努力解决这个问题。

由于

2 个答案:

答案 0 :(得分:2)

  

基本上我想要的   NotificationService,收到一个   导入提供的唯一ID   class,无论何时创建和   由新班组成

您可以将ID(以及需要初始化的事实)添加到INotificationsService合同中:

public interface INotificationsService : IObservable<ReceivedNotification>
{
    /// <summary>
    /// Gets or sets the ID for this notification service. May only be set once.
    /// </summary>
    /// <exception cref="InvalidOperationException">
    /// The setter was called more than once, or the getter was called before the
    /// ID was initialized.
    /// </exception>
    string ID { get; set; }

    void IssueNotifications(IEnumerable<ClientIssuedNotification> notifications);
}

导入可以如下所示:

public class Client
{
    private readonly INotificationsService _notificationsService;

    [Import(typeof(INotificationService), 
        RequiredCreationPolicy = CreationPolicy.NonShared)]
    public INotificationsService NotificationsService
    {
        get
        {
            return _notificationsService;
        }
        set
        {
           _notificationsService = value;
           _notificationsService.ID = "SomeID"; 
        }
    }
}

另一种选择是导入一个接受ID参数的工厂:

public interface INotificationsServiceFactory
{
   INotificationsService Create(string ID);
}

这两种方法都有不同的优点和缺点。例如,初始化导入方法很简单,但它在组件生命周期中引入了额外的阶段(“已创建但尚未初始化”)。

工厂方法避免了这种情况,但它掩盖了您只需要一个实例的事实。如果需要清理,工厂方法也将处理物品的责任从容器转移到工厂客户。

另一个选择是从MEF切换到另一个IoC容器,它可以让您对组件注册和依赖项解析进行更精细的控制,例如Castle Windsor。但是,当然你必须保持配置,这可能会很痛苦。

答案 1 :(得分:1)

您可以导出一个允许您访问插件的代理,例如:

public class Client
{
    [Export("PluginDelegate")]
    IPlugin GetPlugin()
    {
        return new SamplePlugin();
    }

    [Import]
    public INotificationService NotificationService { get; set; }
}

[PartCreationPolicy(CreationPolicy.NonShared)]
public class ClientNotificationService : INotificationService
{
    [Import("PluginDelegate")] Func<IPlugin> PluginDelegate;
}