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?

14

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

  • 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 '17 at 10:44
4

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>
  • 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. – Volodymyr Hil Nov 4 '16 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. – Sean Holmesby Nov 4 '16 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 '16 at 14:14
  • this worked: serviceCollection.AddSingleton<IService, ServiceImplementation>(); serviceCollection.AddSingleton<IExtendedService>( provider => (ServiceImplementation)provider.GetService(typeof(IService))); – Volodymyr Hil Nov 4 '16 at 14:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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