Skip to content

Commit

Permalink
Merge pull request #3 from atc-net/feature/init_services
Browse files Browse the repository at this point in the history
Init Services and ServiceCollectionExtensions
  • Loading branch information
perkops authored May 18, 2024
2 parents 3ce48f0 + de37df1 commit df675c9
Show file tree
Hide file tree
Showing 22 changed files with 2,046 additions and 2 deletions.
17 changes: 16 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -519,4 +519,19 @@ dotnet_diagnostic.S6605.severity = none # Collection-specific "Exist
##########################################
# Custom - Code Analyzers Rules
##########################################
[*.{cs,csx,cake}]
[*.{cs,csx,cake}]

MA0051.maximum_lines_per_method = 100

dotnet_diagnostic.SA1010.severity = none #
dotnet_diagnostic.SA1402.severity = none #
dotnet_diagnostic.SA1615.severity = none #

dotnet_diagnostic.CA1002.severity = none #
dotnet_diagnostic.CA1031.severity = none #
dotnet_diagnostic.CA2007.severity = none # Consider calling ConfigureAwait on the awaited task

dotnet_diagnostic.MA0004.severity = none # Use Task.ConfigureAwait(false) as the current SynchronizationContext is not needed
dotnet_diagnostic.MA0016.severity = none # Prefer returning collection abstraction instead of implementation

dotnet_diagnostic.S3267.severity = none #
2 changes: 2 additions & 0 deletions Atc.Microsoft.Graph.Client.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sharepoint/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
4 changes: 3 additions & 1 deletion src/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,6 @@

##########################################
# Custom - Code Analyzers Rules
##########################################
##########################################

dotnet_diagnostic.IDE0039.severity = none #
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,12 @@
<None Include="..\..\README.md" Link="README.md" Pack="true" PackagePath="\" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Atc" Version="2.0.472" />
<PackageReference Include="Azure.Identity" Version="1.11.3" />
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="8.5.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Microsoft.Graph" Version="5.53.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// ReSharper disable ConvertToLocalFunction
namespace Atc.Microsoft.Graph.Client.Extensions;

public static class ServiceCollectionExtensions
{
private static readonly string[] DefaultScopes = { "https://graph.microsoft.com/.default" };

/// <summary>
/// Adds the <see cref="GraphServiceClient"/> to the service collection.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> instance to augment.</param>
/// <param name="graphServiceClient"><see cref="GraphServiceClient"/> to use for the service. If null, one must be available in the service provider when this service is resolved.</param>
/// <returns>The same instance as <paramref name="services"/>.</returns>
public static IServiceCollection AddMicrosoftGraphServices(
this IServiceCollection services,
GraphServiceClient? graphServiceClient = null)
{
Func<IServiceProvider, GraphServiceClient> factory = (serviceProvider)
=> graphServiceClient ?? serviceProvider.GetRequiredService<GraphServiceClient>();

services.AddSingleton(factory);

RegisterGraphServices(services);

return services;
}

/// <summary>
/// Adds the <see cref="GraphServiceClient"/> to the service collection using the provided <see cref="TokenCredential"/> and optional scopes.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> instance to augment.</param>
/// <param name="tokenCredential">The <see cref="TokenCredential"/> to use for authentication.</param>
/// <param name="scopes">Optional array of scopes for the <see cref="GraphServiceClient"/>.</param>
/// <returns>The same instance as <paramref name="services"/>.</returns>
public static IServiceCollection AddMicrosoftGraphServices(
this IServiceCollection services,
TokenCredential tokenCredential,
string[]? scopes = null)
{
services.AddSingleton(_ => new GraphServiceClient(tokenCredential, scopes ?? DefaultScopes));

RegisterGraphServices(services);

return services;
}

/// <summary>
/// Adds the <see cref="GraphServiceClient"/> to the service collection using the provided <see cref="GraphServiceOptions"/> and optional scopes.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> instance to augment.</param>
/// <param name="graphServiceOptions">The <see cref="GraphServiceOptions"/> containing configuration for the service.</param>
/// <param name="scopes">Optional array of scopes for the <see cref="GraphServiceClient"/>.</param>
/// <returns>The same instance as <paramref name="services"/>.</returns>
/// <exception cref="InvalidOperationException">Thrown if the <paramref name="graphServiceOptions"/> are invalid.</exception>
public static IServiceCollection AddMicrosoftGraphServices(
this IServiceCollection services,
GraphServiceOptions graphServiceOptions,
string[]? scopes = null)
{
ArgumentNullException.ThrowIfNull(graphServiceOptions);

if (!graphServiceOptions.IsValid())
{
throw new InvalidOperationException($"Required service '{nameof(GraphServiceOptions)}' is not registered");
}

services.AddSingleton(_ =>
{
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
};

var clientSecretCredential = new ClientSecretCredential(
graphServiceOptions.TenantId,
graphServiceOptions.ClientId,
graphServiceOptions.ClientSecret,
options);

return new GraphServiceClient(clientSecretCredential, scopes ?? DefaultScopes);
});

RegisterGraphServices(services);

return services;
}

private static void RegisterGraphServices(
IServiceCollection services)
{
services.AddGraphService<IOneDriveGraphService, OneDriveGraphService>();
services.AddGraphService<IOutlookGraphService, OutlookGraphService>();
services.AddGraphService<ISharepointGraphService, SharepointGraphService>();
services.AddGraphService<ITeamsGraphService, TeamsGraphService>();
services.AddGraphService<IUsersGraphService, UsersGraphService>();
}

private static void AddGraphService<TService, TImplementation>(
this IServiceCollection services)
where TService : class
where TImplementation : GraphServiceClientWrapper, TService
{
services.AddSingleton<TService, TImplementation>(s => (TImplementation)Activator.CreateInstance(
typeof(TImplementation),
s.GetRequiredService<ILoggerFactory>(),
s.GetRequiredService<GraphServiceClient>())!);
}
}
Loading

0 comments on commit df675c9

Please sign in to comment.