Wednesday, 7 November 2012

Dependency Injection / Singleton in RIA Domain Service


Many a times there are requirement to share a value/property between multiple Domain Service calls. Problem is on each call we have new instance of the DomainService. i.e. Each time a client calls into the DomainService endpoint, the RIA hosting layer uses the singleton DomainService.Factory to create a new instance of the requested DomainService type. The default IDomainServiceFactory implementation expects a DomainService type to provide a parameter-less constructor. So there is no possibility of injecting the shared property during the creation of Domain Service. In my case scenario was to share a unique instance of the following to multiple Domain Service call –
SerializationService and  SunixAuthService
 
See below the approach –
1.      Created my own custom DomainServiceFactory -
public class SunixDomainServiceProvider : IDomainServiceFactory
{
        private SerializationService _serializationService;
        private SunixAuthService _sunixAuthService;
        public SunixDomainServiceProvider()
        {
            _serializationService = new SerializationService();
            _sunixAuthService = new SunixAuthService();
        }
        public DomainService CreateDomainService(Type domainServiceType, DomainServiceContext context)
        {
            DomainService domainService;
            if (typeof(CustomDomainService) == domainServiceType)
            {
                domainService = new CustomDomainService(_serializationService, _sunixAuthService);
            }
            else
            {
                domainService = (DomainService)Activator.CreateInstance(domainServiceType);
            }

            domainService.Initialize(context);
            return domainService;
        }
        public void ReleaseDomainService(DomainService domainService)
        {
            domainService.Dispose();
        }
}
2. Registed the Factory in the Global.asax
Now that we have a custom factory, we’ll have to make sure it gets used to instantiate our DomainService. The easiest way to do this is to add a Global.asax file to our web site and bootstrap the factory there.
protected void Application_Start(object sender, EventArgs e)
{
    DomainService.Factory = new SunixDomainServiceProvider();
}

3. Now change your DomainService ctor to accept these values –
[EnableClientAccess()]
public class CustomDomainService : LinqToEntitiesDomainService<EntityTestDBEntities>
{
        public CustomDomainService(ISerializationService sss, ISunixAuthService acs)
        {
           
        }
        public IQueryable<School> GetSchools()
        {
            return this.ObjectContext.Schools;
        }
}

Now if you Test the Service you find the constructor of the SunixDomainServiceProvider is hitting only once irrespective of how many calls clients are making. 
        public SunixDomainServiceProvider()
        {
            _serializationService = new SerializationService();
            _sunixAuthService = new SunixAuthService();
        }

Conclusion: If you want to maintain a instance of some property/value then the CustomDomainServicePactory is appropriate place and can’t be achieved at the DomainService itself.