# Services & Configuration

When writing extensions for SanteDB in .NET, developers will create a series of supporting classes and implementations of SanteDB services which should be configurable based on their context and runtime environment.

This section describes the classifications of services which can be implemented in SanteDB, as well as the support classes to handle configuration of these custom services.

## Use of Services

Whenever you write a plugin for SanteDB, you are actually implementing and consuming a series of service contracts. Whenever another plugin wants a particular service it will ask the host context for the currently configured service instance and call the relevant method on the contract.

Alternately, when you wish to call a service you must ask for the current implementation. There are two methods to do this:

* Service Locator Pattern (<https://en.wikipedia.org/wiki/Service_locator_pattern>) - Whereby service instances are located at runtime
* Dependency Injection Pattern (<https://en.wikipedia.org/wiki/Dependency_injection>) - Whereby services instances are injected into the class when constructed.

### Service Locator

You should use the service locator pattern when:

* Your plugin needs to operate on SanteDB iCDR and dCDR versions < 2.0.76
* Your plugin is going to use dynamic services (like IDataPersistenceService<> and IRepositoryService<>) where the services are registered at runtime.

Using the service locator pattern, your extension should:

* Get the current instance of the `ApplicationServiceContext.Current` class
* Call the `GetService<T>()` method passing the contract to the method
* Verify the service was registered by doing a null check.

Consider a service which finds a patient.

```csharp
public interface IPatientFinderService : IServiceImplementation {
     Patient FindPatient(string id);
}

public class PatientFinderProvider : IPatientFinderService {
     
     public string Name => "My Extended Service";
     
     public Patient FindPatient(string id) {
          // Get the repository service
          var repo = ApplicationServiceContext.Current.GetService<IRepositoryService<Patient>>();
          // Check if repository was null
          if(repo == null)
              throw new InvalidOperationException("Couldn't find a valid Patient Repository");
         
          // Return the patient
          return repo.Find(p=>p.Identifiers.Any(i=>i.Value == id)).FirstOrDefault();
     }
     
}
```

### Dependency Injection

Dependency injection was introduced in SanteDB 2.0.76 , you can use dependency injection when:

* Your plugin is targeting SanteDB iCDR > 2.0.76
* The services being injected are configured services not registered at runtime (i.e. they aren't dynamically generated)

Dependency injection is driven off the constructor, rules for this are:

* Your object should not define a default constructor (the DI code will assume you're using Service Locator instead)
* Should identify the required services using the service contract definition
* Should identify option services using a default value of null

Using our example from above, let's imagine we want to extend our class to cache the located result and to hash the identifier in the cache. Since the hashing and caching services are defined statically in the configuration file, we can use DI for this.

```csharp
public class PatientFinderProvider : IPatientFinderService {
     
     public string Name => "My Extended Service";
     
     // Add: Local references to static services
     private IAdHocCacheService adhocCache;
     private IPasswordHashingService hashingService;
     
     // Constructor indicating services required
     public PatientFinderProvider(IAdHocCacheService adHocCache, IPasswordHashingService hashingService)
     {
          this.adhocCache = adHocCache;
          this.hashingService = hashingService;
     }
     
     public Patient FindPatient(string id) {
     
          // Get the repository service
          var repo = ApplicationServiceContext.Current.GetService<IRepositoryService<Patient>>();
          // Check if repository was null
          if(repo == null)
              throw new InvalidOperationException("Couldn't find a valid Patient Repository");
         
          // Check if the patient exists in the cache
          var key = this.hashingService.ComputeHash(id);
          var patient = this.adhocCache.Get<Patient>(key);
          if(patient == null) // Load from DB
          {
               patient = repo.Find(p=>p.Identifiers.Any(i=>i.Value == id)).FirstOrDefault();
               this.adhocCache.Add(key, patient);
          }
          return patient;
     }
     
}
```

## Related Topics

{% content-ref url="/spaces/-LZ0\_pjgTp\_kx4hqTZ3a/pages/-MGJUFhcBlz2AtNsUNWP" %}
[Configuration](/developers/server-plugins/implementing-.net-features/configuration.md)
{% endcontent-ref %}

{% content-ref url="/spaces/-LZ0\_pjgTp\_kx4hqTZ3a/pages/-MGIdZ-3EiHGG0AwI0At" %}
[Passive Services](/developers/server-plugins/implementing-.net-features/passive-services.md)
{% endcontent-ref %}

{% content-ref url="/spaces/-LZ0\_pjgTp\_kx4hqTZ3a/pages/-MGG26iz5zykpWbq06WE" %}
[Daemon Services](/developers/server-plugins/implementing-.net-features/daemon-services.md)
{% endcontent-ref %}

{% content-ref url="/spaces/-LZ0\_pjgTp\_kx4hqTZ3a/pages/-MDKWMbwTYctwpsULKjO" %}
[Service Definitions](/developers/server-plugins/implementing-.net-features/service-definitions.md)
{% endcontent-ref %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://help.santesuite.org/developers/server-plugins/implementing-.net-features.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
