views:

49

answers:

2

Hi,

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

A: 

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;
}
Matthew Abbott
+1  A: 

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.

Wim Coenen
Thanks for the answer, but what I really need is some king of 'scoping' solution, a solution that would automatically resolve such and issue. I need to research more on this matter to see how can I implement such a solution.
Pop Catalin