【问题标题】:MEF: Satisfy part on an Export using and Export from the composed partMEF:使用组合部分满足导出部分和导出部分
【发布时间】:2011-03-04 22:54:47
【问题描述】:

我在 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,无论何时创建并组合到新类, 或者如果有其他方法,比如使用元数据来做到这一点,我会很感激任何见解。我已经为此苦苦挣扎了一段时间。

谢谢

【问题讨论】:

    标签: c# .net silverlight mef composition


    【解决方案1】:

    基本上我想要 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。但是你当然必须维护配置,这可能会很痛苦。

    【讨论】:

    • 感谢您的回答,但我真正需要的是一些“范围界定”解决方案之王,一种可以自动解决此类问题的解决方案。我需要对此问题进行更多研究,以了解如何实施这样的解决方案。
    【解决方案2】:

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

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2015-05-12
      相关资源
      最近更新 更多