2

我在 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 使用 Client 类导出的 IPlugin 来满足 ClientNotificationService.Plugin 部分。

基本上,我希望 NotificationService 接收导入类提供的唯一 ID,无论何时它被创建并组合到一个新类,或者如果有其他方法,比如使用元数据来做到这一点,我会很感激任何见解。我已经为此苦苦挣扎了一段时间。

谢谢

4

2 回答 2

2

基本上我希望 NotificationService 接收导入类提供的唯一 ID,只要它被创建并组合到一个新类

您可以将 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);
}

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

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

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

于 2010-06-18T09:47:50.360 回答
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;
}
于 2010-06-18T08:47:18.447 回答