1
Vote

Singleton not working

description

Hi,

So I have a service class, for example:
[Export]
[Singleton]
public class MyService : NotifyObject
{
}
When I import this service into multiple view models, the service is a different instance. So the Singleton attribute doesn't seem to work. I want the service and all properties to be shared between view models same as with MEF's PartCreationPolicy attribute.
[Import]
public MyService Service { get; set; }
Am I doing something wrong or is this an actual issue with 3.1.5?

comments

ipjohnson123 wrote Feb 13, 2014 at 2:21 PM

Hi mitypatel,

I think I know what's happening, in StyleMVVM when you mark a type with [Export] without providing the type it exports that service by the class name rather than by type (i.e. MyService rather than typeof(MyService).

The reason you are getting transient objects instead of the singleton is because when it goes to resolve MyService by type there is no service registered by that type and automatically constructs the concrete type as a transient.

This behavior is going to change in 4.0 and [Export] will default to exporting by type rather than class name, but that doesn't solve your problem now.

For the moment what you can do is change your [Export] attribute to look like

[Export(typeof(MyService))]
[Singleton]
public class MyService : NotifyObject
{
}

That will export your class by type and your Import statement is already setup to import by type.

Sorry for the confusion
-Ian

mitypatel wrote Feb 13, 2014 at 4:42 PM

Hi Ian,

Thanks for your prompt response. Unfortunately, that didn't seem to solve the Singleton issue.

I'm not sure if this is related, however if I remove the Export attribute and the Singleton attribute, MyService is still resolved, which is a little strange/ counter intuitive. Maybe when it's imported the container resolves the service automatically by name?!

If I import like the following the app hangs.
[Import(ImportName = "MyService")]
public MyService MyService { get; set; }
Any other ideas?
Your help is greatly appreciated.

Thanks,
Mit

ipjohnson123 wrote Feb 13, 2014 at 5:18 PM

Hi Mit,

I have to say I'm rather surprised there are a number of unit tests revolving around the singleton attribute.

Could you put together a sample showing the problem or maybe send your project along and I can look.

The container will auto register concrete types as transients that's why when you remove the attributes it will still resolve the service. If you where referring to it by an interface it would fail.

-Ian

mitypatel wrote Feb 14, 2014 at 12:09 PM

Umm... Embarrassingly I forgot to register my assembly with the container in App.xaml.cs. MyService was actually located in a separate assembly. I've posted my test app to you anyway.

Apologies.
/// <summary>
///   Creates the bootstrapper.
/// </summary>
private void CreateBootstrapper()
{
  if (!Bootstrapper.HasInstance)
  {
    var newBootstrapper = new Bootstrapper();

    newBootstrapper.Container.RegisterAssembly(this.GetType()
                                                   .GetTypeInfo()
                                                   .Assembly);

    //DOH!
    newBootstrapper.Container.RegisterAssembly(typeof(MyService)
                                                   .GetTypeInfo()
                                                   .Assembly);

    // Required for Validation
    newBootstrapper.Container.RegisterAssembly(typeof (CSharpContainerLoader).GetTypeInfo()
                                                                             .Assembly);

    newBootstrapper.Start(false);
  }
}