MEF:使用并从组合零件导出来满足导出零件的要求

发布于 2024-09-06 12:19:41 字数 980 浏览 6 评论 0原文

我在 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 的导入类提供。

例如:

Snippet

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

    [Import]
    INotificationService NotificationService;
}

我怎么能说我希望 MEF 通过 Client 类导出的 IPlugin 来满足 ClientNotificationService.Plugin 部分。

基本上我希望NotificationService能够接收由导入类提供的唯一ID,每当它被创建并组成一个新类时, 或者如果有替代方法,例如使用元数据来执行此操作,我将不胜感激。我已经为此苦苦挣扎了一段时间。

谢谢

I have the following scenario in Silverlight 4:

I have a notifications service

Snippet

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

and and implementation of this service
Snippet

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

How can I say to MEF that the Plugin property of the ClientNotificationService must be provided by the importing class that imports the INotificationsService.

For example:

Snippet

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

    [Import]
    INotificationService NotificationService;
}

How can I say that I want MEF to satisfy the ClientNotificationService.Plugin part with the exported IPlugin by the Client class.

Basically I want the NotificationService, to receive a Unique ID provided by the importing class, whenever it is created and composed to a new class,
or if there's and alternative method, like using meta data to do this I'd appreciate any insights. I've been struggling with this for a while.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

朱染 2024-09-13 12:19:41

基本上我想要
通知服务,接收
导入时提供的唯一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);
}

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

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

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

Basically I want the
NotificationService, to receive a
Unique ID provided by the importing
class, whenever it is created and
composed to a new class

You could add the ID (and the fact that it needs to be initialized) to the INotificationsService contract:

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

An import can then look like this:

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

Another option is to import a factory which accepts an ID parameter:

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

Both approaches have different strengths and weaknesses. For example, the initialize-on-import approach is straightforward but it introduces an extra phase in the components lifetime ("created but not yet initialized").

The factory approach avoids this but it obscures the fact that you only need one instance. If clean-up is needed, the factory approach also shifts responsibility for disposing things from the container to the factory client.

Yet another option is to switch from MEF to another IoC container which gives you more fine grained control over the component registration and dependency resolution, like Castle Windsor. But then you'll have to maintain the configuration of course, which might be a pain.

゛时过境迁 2024-09-13 12:19:41

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

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

You could export a delegate which will allow you access to your plugin, e.g.:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文