How can I register services in Kephas using a fluent API?

19 Views Asked by At

I want to preserve the DI abstraction layer Kephas provides, but in my particular case I need to register a service which is imported from a third-party library. Given this, I cannot annotate the service with the [AppServiceContract] attribute required for service registration. Is there a way to achieve this?

1

There are 1 best solutions below

0
ioan On BEST ANSWER

Yes there is. Here are the steps to follow:

  • Define a class implementing IConventionsRegistrar.
  • Use the conventions builder to register the desired services.

Sample code:

public class MyConventionsRegistrar : IConventionsRegistrar
{
    /// <summary>
    /// Registers the conventions.
    /// </summary>
    /// <param name="builder">The registration builder.</param>
    /// <param name="candidateTypes">The candidate types which can take part in the composition.</param>
    /// <param name="registrationContext">Context for the registration.</param>
    public void RegisterConventions(
        IConventionsBuilder builder,
        IEnumerable<TypeInfo> candidateTypes,
        ICompositionRegistrationContext registrationContext)
    {
        //... here you can use the conventions builder to register your services using the fluent API. The candidate types are provided if you need the  identified application types. A couple of examples are provided below:

        // shared/singleton service exported as IMyService with MyService implementation.
        builder.ForType(typeof(MyServiceImpl))
               .Export(b => b.AsContractType(typeof(IMyService)))
               .Shared();

        // instance-based multiple services exported as IMultiImplService
        builder.ForTypesDerivedFrom(typeof(IMultiImplService))
               .Export(b => b.AsContractType(typeof(IMultiImplService)));
    }

There is a second way of registering services, however by the means of service descriptors instead of a fluent API. For this case, follow the steps:

  • Define a class implementing IAppServiceInfoProvider.
  • Return the descriptors of the desired services.

Sample code with the same registrations as above:

public class MyAppServiceInfoProvider : IAppServiceInfoProvider
{
    /// <summary>
    /// Gets an enumeration of application service information objects.
    /// </summary>
    /// <param name="candidateTypes">The candidate types which can take part in the composition.</param>
    /// <param name="registrationContext">Context for the registration.</param>
    /// <returns>
    /// An enumeration of application service information objects and their associated contract type.
    /// </returns>
    public IEnumerable<(TypeInfo contractType, IAppServiceInfo appServiceInfo)> GetAppServiceInfos(IEnumerable<TypeInfo> candidateTypes, ICompositionRegistrationContext registrationContext)
    {
        yield return (typeof(IMyService).GetTypeInfo(), 
                      new AppServiceInfo(typeof(IMyService), 
                                         typeof(MyServiceImpl),
                                         AppServiceLifetime.Shared));
        yield return (typeof(IMultiImplService).GetTypeInfo(), 
                      new AppServiceInfo(typeof(IMultiImplService), 
                                         AppServiceLifetime.Instance, 
                                         allowMultiple: true));
    }

Both cases are autodiscovered and, at the proper time, the registration methods are called. However, in the second case, the advantage is that the registrations are available as service metadata for querying at a later time.