mirror of
https://github.com/dotnet/skills.git
synced 2026-09-20 09:49:54 +08:00
042a9d2b2c
* Reorganize plugins per agreed structure (#271) Split the dotnet plugin into domain-specific plugins per discussion in #271: - dotnet: narrowed to common everyday C#/.NET coding tasks - dotnet-diag: perf investigations, debugging, incident analysis - dotnet-data: data access and Entity Framework - dotnet-aspnet, dotnet-wpf, dotnet-winforms, dotnet-maui: scaffolded empty to convey intent for future framework-specific skills Moved skills, tests, and CODEOWNERS entries accordingly. No file content was changed; all skill/test moves are pure renames. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Improve dotnet-diag and dotnet-winforms descriptions - dotnet-diag: add '.NET' qualifier to clarify scope - dotnet-winforms: use official 'Windows Forms (WinForms)' name Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add .NET qualifier to dotnet-data description Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove empty plugins; list them in CONTRIBUTING.md as future options Remove the four empty placeholder plugins (dotnet-aspnet, dotnet-wpf, dotnet-winforms, dotnet-maui) that had only plugin.json and no skills. Add a 'Plugin organization' section to CONTRIBUTING.md that describes the domain-specific plugin groupings introduced in this PR and lists the four removed plugin names as reserved candidates for future contributions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Create dotnet-upgrade plugin with migration/upgrade skills Move migrate-nullable-references, thread-abort-migration, and dotnet-aot-compat from dotnet to the new dotnet-upgrade plugin. Update CODEOWNERS paths (same owners), CONTRIBUTING.md plugin table, and fix the thread-abort-migration SKILL.md link in CONTRIBUTING.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
83 lines
2.8 KiB
C#
83 lines
2.8 KiB
C#
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
#nullable enable
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Azure.Core;
|
|
|
|
namespace Azure.ResourceManager
|
|
{
|
|
/// <summary>
|
|
/// helper class
|
|
/// </summary>
|
|
internal static class SharedExtensions
|
|
{
|
|
/// <summary>
|
|
/// Collects the segments in a resource identifier into a string
|
|
/// </summary>
|
|
/// <param name="resourceId">the resource identifier</param>
|
|
/// <returns></returns>
|
|
public static string SubstringAfterProviderNamespace(this ResourceIdentifier resourceId)
|
|
{
|
|
const string providersKey = "/providers/";
|
|
var rawId = resourceId.ToString();
|
|
var indexOfProviders = rawId.LastIndexOf(providersKey, StringComparison.InvariantCultureIgnoreCase);
|
|
if (indexOfProviders < 0)
|
|
return string.Empty;
|
|
var whateverRemains = rawId.Substring(indexOfProviders + providersKey.Length);
|
|
var firstSlashIndex = whateverRemains.IndexOf('/');
|
|
if (firstSlashIndex < 0)
|
|
return string.Empty;
|
|
return whateverRemains.Substring(firstSlashIndex + 1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// An extension method for supporting replacing one dictionary content with another one.
|
|
/// This is used to support resource tags.
|
|
/// </summary>
|
|
/// <param name="dest"> The destination dictionary in which the content will be replaced. </param>
|
|
/// <param name="src"> The source dictionary from which the content is copied from. </param>
|
|
/// <returns> The destination dictionary that has been altered. </returns>
|
|
public static IDictionary<string, string> ReplaceWith(this IDictionary<string, string> dest, IDictionary<string, string> src)
|
|
{
|
|
dest.Clear();
|
|
foreach (var kv in src)
|
|
{
|
|
dest.Add(kv);
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
public static async Task<TSource?> FirstOrDefaultAsync<TSource>(
|
|
this AsyncPageable<TSource> source,
|
|
Func<TSource, bool> predicate,
|
|
CancellationToken token = default)
|
|
where TSource : notnull
|
|
{
|
|
if (source == null)
|
|
throw new ArgumentNullException(nameof(source));
|
|
if (predicate == null)
|
|
throw new ArgumentNullException(nameof(predicate));
|
|
|
|
token.ThrowIfCancellationRequested();
|
|
|
|
await foreach (var item in source.ConfigureAwait(false))
|
|
{
|
|
token.ThrowIfCancellationRequested();
|
|
|
|
if (predicate(item))
|
|
{
|
|
return item;
|
|
}
|
|
}
|
|
|
|
return default;
|
|
}
|
|
}
|
|
}
|