Singleton and IISReset

Aug 15, 2010 at 7:07 PM

Hi,

I have registered a type as singleton. I've used Feature receiver to register type and as soon as I register type with feature receiver as singleton, I have found the singleton is working. However once IIS is reset, the singleton behavior is not maintained and the instance is being created on each request as I have found putting breakpoint in constructor. Is this as designed or bug? The expected behavior should be after IIS reset, "create an instance of singleton type on first request and later on use the same object until next IIS reset".

 

Thanks

Sohel

http://ranaictiu-technicalblog.blogspot.com/

Coordinator
Aug 16, 2010 at 3:41 AM

Hi,

 

Could you please provide your registration code?  That doesn't make sense to me, I'm wondering if you registered using ActivatingServiceLocator, in which case the registration is in memory?  You should be using ServiceLocatorConfig to register services, which writes the registration information to the configuration store.

 

Thanks,

Chris

Aug 16, 2010 at 5:44 AM

Hi Chris,

Yes I'm using ActivatingStore for registering Singleton instance. However for registering non-singleton instance I'm using ServiceLocatorConfig. As I have found ServiceLocatorConfig doesn't have way to register singleton instance. Logically I think the singleton instance should go with ActivatingStore as everytime the w3p process will start the singlton instance will be created. Is it possible to use ServiceLocatorConfig to register singleton instance? Or is it possible in any other way to register singleton instance so that on every IIS reset a new instance is created and shared as singleton for that IIS lifespan?

 

Here's the code I have used in feature receiver to register type mappings:

var serviceLocator = SharePointServiceLocator.GetCurrent(currentSite);
var serviceLocatorconfig = serviceLocator.GetInstance<IServiceLocatorConfig>();
serviceLocatorconfig.Site = currentSite;

//non-singleton registration
serviceLocatorconfig.RegisterTypeMapping<ILeftNavigationItem, LeftNavigationItem>();
serviceLocatorconfig.RegisterTypeMapping<ILeftNavigationManager, LeftNavigationManager>();
            
//singleton registration
var activatingServiceLocator = (ActivatingServiceLocator)serviceLocator;
activatingServiceLocator.RegisterTypeMapping<IGetProductiveSharePointConfigurationProvider, GetProductiveSharePointConfigurationProvider>(InstantiationType.AsSingleton);

Coordinator
Aug 17, 2010 at 2:32 PM

Hi,

I can see why you are doing this, we have a documentation bug.  This is the right way for unit testing, but not for actualregistration. 

The interface doesn't support registering singletons, so you need to go directly to the ServiceLocatorConfig class.  I did a quick spike to show this, and the following is an example of how to register a singleton at the site collection level (they can be registered for a farm or site collection.  When registered as a farm, it will apply to every access within the app domain for that process.  When registered at site collection, it will apply for every site in the site collection within the app domain for that process.  If the same interface is registered for a site collection and for the farm for a singleton, then the site collection instance will be returned for sites within the site collection, while the farm will be returned everywhere else:

Here is the code in the feature receiver:

    public class TestSingletonFeatureEventReceiver : SPFeatureReceiver
    {
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            var site = properties.Feature.Parent as SPSite;

            var config = SharePointServiceLocator.GetCurrent(site).GetInstance<IServiceLocatorConfig>() as ServiceLocatorConfig;
            config.RegisterTypeMapping<ITestSingleton, TestSingleton>(null, InstantiationType.AsSingleton);

        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            var site = properties.Feature.Parent as SPSite;

            var config = SharePointServiceLocator.GetCurrent(site).GetInstance<IServiceLocatorConfig>() as ServiceLocatorConfig;
            config.RemoveTypeMapping<ITestSingleton>(null);
        }

 Here is the code for my web part:

    public interface ITestSingleton
    {
        int GetCount();
    }

    public partial class VisualWebPart1UserControl : UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            var singleton = SharePointServiceLocator.GetCurrent().GetInstance<ITestSingleton>();
            this.Literal1.Text = singleton.GetCount().ToString();
        }
    }

    public class TestSingleton : ITestSingleton
    {
        int count = 0;

        public int GetCount()
        {
            count++; 
            return count;
        }
    }

 

When I refresh the page, the count goes up by 1 each time as expected for a singleton instance.

Please let me know if you have any further issues.  We will fix the documentation as well.

Chris

 

 

 

 

 

Aug 18, 2010 at 7:11 PM

Thanks Cris, It worked.