MEF: Удовлетворить деталь при использовании Экспорта и Экспортировать из составной части - PullRequest
2 голосов
/ 17 июня 2010

У меня есть следующий сценарий в 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, что свойство Plugin ClientNotificationService должно быть предоставлено импортирующим классом, который импортирует INotificationsService.

Например:

Отрывок

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

    [Import]
    INotificationService NotificationService;
}

Как я могу сказать, что я хочу, чтобы MEF удовлетворил часть ClientNotificationService.Plugin с экспортированным IPlugin классом Client.

По сути, я хочу, чтобы служба NotificationService получала уникальный идентификатор, предоставленный импортирующим классом, всякий раз, когда он создается и объединяется в новый класс, или, если есть и альтернативный метод, например, использование метаданных для этого, я буду признателен за любые идеи. Я боролся с этим некоторое время.

Спасибо

Ответы [ 2 ]

2 голосов
/ 18 июня 2010

По сути, я хочу, чтобы служба NotificationService получала уникальный идентификатор, предоставленный импортирующим классом, всякий раз, когда он создается и объединяется с новым классом

Вы можете добавить идентификатор (ифакт, что он должен быть инициализирован) к 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 голос
/ 18 июня 2010

Вы можете экспортировать делегата, который предоставит вам доступ к вашему плагину, например ::100100

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