9

When using the native Sitecore Dependency Injection I have 2 abstrations:

  • IService
  • IExtendedService

I want them both to be registered to same singleton instance of a ServiceImplementation

How do I register the implementation with my IoC Container to do that?

2 Answers 2

15

Same instance for multiple services

I believe this can only be achieved with code registration:

var implementation = new ServiceImplementation();

serviceCollection.AddSingleton<IService>(provider => implementation);
serviceCollection.AddSingleton<IExtendedService>(provider => implementation);

In case ServiceImplementation has its own dependencies, you will need to instantiate it from the container as well. Here's a trick you can use:

serviceCollection.AddSingleton<IService, ServiceImplementation>();
serviceCollection.AddSingleton<IExtendedService>(
    provider => (ServiceImplementation)provider.GetService(typeof(IService)));

Below you can find more general details that I typed in before fully understanding the question :)

XML registration

If you're using XML registration, just add a .config patch file with the following contents:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <services>
      <register
        serviceType="[Namespace].IService, [Assembly]"
        implementationType="[Namespace].ServiceImplementation, [Assembly]"
        lifetime="Singleton" />
      <register
        serviceType="[Namespace].IExtendedService, [Assembly]"
        implementationType="[Namespace].ServiceImplementation, [Assembly]"
        lifetime="Singleton" />
    </services>
  </sitecore>
</configuration>

Code registration

You should use Sitecore configurators to register dependencies from code.

There are many available registration methods. Here's an example with a singleton dependency:

serviceCollection.AddSingleton<IExtendedService, ServiceImplementation>;

A transient example:

serviceCollection.AddTransient<IService>(provider => new ServiceImplementation());

To see the complete list of available registration methods, decompile the class ServiceCollectionServiceExtensions in the assembly Microsoft.Extensions.DependencyInjection.Abstractions. The main variations are:

  • AddTransient<...>(...)
  • AddScoped<...>(...)
  • AddSingleton<...>(...)
  • Add(Type, Type, ServiceLifetime)
  • Add(Type, Func<IServiceProvider, object>, ServiceLifetime)

Dependency lifetime

Regardles of which registration method you choose, remember to specify an appropriate lifetime scope. The supported options are:

  • Singleton
  • Scoped
  • Transient

Further reading

1
  • Good answer, that helped a lot (especially if serviceImplementation has it's own dependencies). One hint/remark: GetService also has a generic interface which to me looks nicer :)
    – FrankyBoy
    Dec 13, 2017 at 10:44
5

You should be able to register the two interfaces to the same singleton instance implementation, but only in code, not in config.

ServiceImplementation impl = new ServiceImplementation();
serviceCollection.AddSingleton<IService>(provider => impl);
serviceCollection.AddSingleton<IExtendedService>(provider => impl);

This kinda sucks because you're newing up the singleton instance here....but it'll work.

I originally attempted this in config, however this DOES NOT WORK.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <services>
            <register 
                serviceType="MyContracts.MyNamespace.IService, MyContracts" 
                implementationType="MyProject.MyNamespace.ServiceImplementation, MyProject" 
                lifetime="Transient" />
            <register serviceType="MyContracts.MyNamespace.IExtendedService, MyContracts" 
                implementationType="MyProject.MyNamespace.ServiceImplementation, MyProject" 
                lifetime="Transient" />
        </services>
    </sitecore>
</configuration>
4
  • 2
    Are we sure that these will give same instance? I will rephrase: I want to register a singleton. The implementation class implements 2 interfaces: IService, IExtendedService So if I get 2 instances: var service = ServiceLocator.ServiceProvider.GetService<IService>(); var extendedService = ServiceLocator.ServiceProvider.GetService<IExtendedService>(); I want them to be same instance. Nov 4, 2016 at 13:30
  • Updated the answer. Yeah, after testing, doing it in config doesn't work. You can follow the way I did it above, which isn't great and is a side effect of the .NET Core conforming container problem. Nov 4, 2016 at 14:13
  • If you make the factory registration for one interface ServiceLocate the other interface, you should get a single instance for both interfaces.
    – Richard Seal
    Nov 4, 2016 at 14:14
  • this worked: serviceCollection.AddSingleton<IService, ServiceImplementation>(); serviceCollection.AddSingleton<IExtendedService>( provider => (ServiceImplementation)provider.GetService(typeof(IService))); Nov 4, 2016 at 14:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.