I am trying to utilize a library written to add Sharepoint functionality. Here is how the SharepointClient
class is constructed in the library.
public class SharePointClient : ISharePointClient
{
private readonly SafeILogger<SharePointClient> _logger;
private readonly SharePointClientConfig _clientConfig;
private readonly GraphServiceClient _graphClient;
public SharePointClient(SafeILogger<SharePointClient> logger,
IOptions<SharePointClientConfig> clientConfig)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_clientConfig = clientConfig.Value ?? throw new
ArgumentNullException(nameof(clientConfig));
_graphClient = GetAuthenticatedGraphClient();
}
}
The method to add the utility library looks like this
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddSharePointUtils(this IServiceCollection services)
{
services.AddOptions<SharePointClientConfig>()
.BindConfiguration("SharePointClientConfig")
.ValidateDataAnnotations()
.ValidateOnStart();
services.AddScoped<ISharePointClient, SharePointClient>();
return services;
}
}
I have a FileUploader
class that takes the SharepointClient
class in the constructor which I need to instantiate through dependency injection.
public class FileUploader : IFileUploader
{
private readonly ISharePointClient _sharePointClient;
public FileUploader(ISharePointClient sharePointClient)
{
_sharePointClient = sharePointClient ?? throw new ArgumentNullException(nameof(sharePointClient));
}
public async Task UploadFile(string fileSourceFilePath, string fileName)
{
await _sharePointClient.UploadFileToDrive("TestPath", "Test",
fileSourceFilePath, fileName);
}
}
Now I have used the utility in a .NET 8 API project and the DI works perfectly.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSafeILogger();
builder.Services.AddSharePointUtils();
builder.Services.AddScoped<IFileUploader, FileUploader>();
But when I am trying to implement it in a .NET 8 console app, I get this error:
var services = new ServiceCollection();
services.AddSafeILogger();
services.AddScoped<IFileUploader, FileUploader>();
services.AddSharePointUtils();
var serviceProvider = services.BuildServiceProvider();
var fileUploader = serviceProvider.GetRequiredService<IFileUploader>();
'Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger'1[Common.SharePoint.Utils.SharePointClient]' while attempting to activate 'Common.Api.Logging.SafeILogger'1[Common.SharePoint.Utils.SharePointClient]'.'
The method AddSafeILogger()
resolves this dependency in the API project, but it is failing to resolve the dependency in Console application.
Here is the AddSafeILogger
:
namespace Common.Api.Logging;
public static class IServiceCollectionExtensions
{
public static IServiceCollection AddSafeILogger(this IServiceCollection services)
{
services.TryAddSingleton(typeof(SafeILogger<>));
return services;
}
}
SafeILogger
is a class inherited from Microsoft.Extensions.Logging.Ilogger
I am not sure why the DI implementation is working for API application, but in the console app when I am trying to instantiate FileUploader
by calling GetRequiredService
method, I am getting the mentioned dependency error. DI for other custom classes work fine in the console app.
You can use the same hosting infrastructure in a console application by using the same Generic Host :
var builder = Host.CreateDefaultBuilder(args);
builder.Services.AddSafeILogger();
builder.Services.AddSharePointUtils();
builder.Services.AddScoped<IFileUploader, FileUploader>();
var app=builder.Build()
var client=app.Services.GetRequiredService<ISharePointClient>();
...