The ServiceClient class you refer to implements IDisposible, so it should be disposed explicitly once you are done with it, otherwise you may end up with memory leaks or other issues. The issue you have here is that you are scoping CrmRepository, and not scoping ServiceClient, therefore not explicitly managing the ServiceClient's lifetime.
A "scoped" service exists in memory for as long as the scope lasts for. This is different depending on the context of the application. To answer accurately, we would need to know if this is a WebAPI app, an MVC app, or a Blazor app etc.
Generally speaking you should be registering as many dependencies as possible using your IoC container so you can manage the scope of every dependency independently. However, in this instance - purely because the ServiceClient class is a black box, I would simply treat the CrmRepository as a grey box, remove the ServiceClient dependency (which I can see has no further abstractions from the documentation - making it generally difficult to mock, and therefore making registering it as a dependency relatively pointless), and write integration tests for the CrmRepository itself.
Your code would therefore end up as:
Registration:
services.Configure<CrmRepoOptions>("path:to:your:connectionString");
services.AddScoped<ICrmRepository, CrmRepository>();
Implementation:
public class CrmRepoOptions
{
public string ConnectionString { get; set; }
}
public class CrmRepository: ICrmRepository
{
private readonly CrmRepoOptions _opt;
public CrmRepository(IOptions<CrmRepoOptions> opt)
{
_opt = opt.Value;
}
public Task DoSomethingWithServiceClient()
{
using(var serviceClient = new ServiceClient(_opt.ConnectionString))
{
// Do your magic with serviceClient
}
return Task.CompletedTask;
}
}
It is unlikely you would want the ServiceClient instance to exist for the entire scope of the CrmRepository (I expect you only need it when DoSomethingWithServiceClient is called), but if you did want it to exist for as long as the CrmRepository for a particular reason, you would be better off implementing IDisposible in the CrmRepository, creating the ServiceClient in the CrmRepository's constructor, and dispose of it in the Dispose method:
public class CrmRepository: IDisposable, ICrmRepository
{
private readonly CrmRepoOptions _opt;
private Serviceclient _sc;
public CrmRepository(IOptions<CrmRepoOptions> opt)
{
_opt = opt.Value;
_sc = new ServiceClient(_opt.ConnectionString);
}
public Task DoSomethingWithServiceClient()
{
// Do your magic with _sc
return Task.CompletedTask;
}
/// <inheritdoc />
public void Dispose()
{
// Not production ready - implement a proper dispose pattern here
_sc.Dispose();
}
}
Have a think about how you want to use ServiceClient and if you need a new instance of it every time you call your method or not. The documentation likely has details around how it manages its internal connections. It may be that a scoped or singleton instance is a really bad idea, and the example code is the recommended way to use it.
-- EDIT --
As comments here have eluded to, you can also register the ServiceClient as a scoped class in your IoC container, meaning you would not have to instantiate it directly when you register the CrmRepository. Whilst this is achievable, the issue you will have here is that if the ServiceClient is injected into other classes (transient or scoped) that are created as part of the same WebAPI request, then the same ServiceClient instance will be used there too.
I do not believe you want to do this here; I believe that the first code example in my response above is actually what you're looking to do; create the ServiceClient whenever you need it, then dispose of it immediately once you have finished working with it. As with many "connection" type classes provided by MS, it is very likely some kind of connection management and / or pooling is happening in the background, and creating and maintaining a persistent (either singleton or scoped) connection will cause you issues in the future. What you are trying to do is likely an over-optimisation in this instance.