From bc86ad2965a9823dcae2f640e28186c1b9ef4edf Mon Sep 17 00:00:00 2001 From: Nikolay Tatarinov Date: Mon, 19 Jan 2026 17:25:41 +0300 Subject: [PATCH] Add IsExternalInit type, BaseCmdlet class, and SessionStatus enum Introduce the IsExternalInit type for C# 9 records compatibility in .NET Standard 2.1. Implement BaseCmdlet class to provide common functionality for cmdlets, including methods for writing results and handling async operations. Add SessionStatus enum to represent API session states. --- classlib/Cmdlets/BaseCmdlet.cs | 114 +++++++++++++++++++++++++++++++++ classlib/IsExternalInit.cs | 23 +++++++ classlib/enum/SessionStatus.cs | 22 +++++++ 3 files changed, 159 insertions(+) create mode 100644 classlib/Cmdlets/BaseCmdlet.cs create mode 100644 classlib/IsExternalInit.cs create mode 100644 classlib/enum/SessionStatus.cs diff --git a/classlib/Cmdlets/BaseCmdlet.cs b/classlib/Cmdlets/BaseCmdlet.cs new file mode 100644 index 0000000..83dc9d3 --- /dev/null +++ b/classlib/Cmdlets/BaseCmdlet.cs @@ -0,0 +1,114 @@ +namespace PS.IPAM.Cmdlets; + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Management.Automation; +using PS.IPAM.Helpers; + +/// +/// Base class for all PS.IPAM cmdlets providing common functionality. +/// +public abstract class BaseCmdlet : PSCmdlet +{ + /// + /// Writes the result to the pipeline, handling both single objects and collections. + /// + /// The result to write to the pipeline. + protected void WriteResult(object? result) + { + if (result == null) + { + return; + } + + if (result is IEnumerable enumerable && result is not string) + { + foreach (var item in enumerable) + { + WriteObject(item); + } + } + else + { + WriteObject(result); + } + } + + /// + /// Converts custom fields from various formats to a dictionary. + /// + /// The custom fields object to convert. + /// A dictionary of custom field names and values. + protected static Dictionary ConvertCustomFields(object? customFields) + { + if (customFields == null) + { + return new Dictionary(); + } + + if (customFields is PSObject psobj) + { + var dict = new Dictionary(); + foreach (var prop in psobj.Properties) + { + dict[prop.Name] = prop.Value ?? string.Empty; + } + return dict; + } + + if (customFields is Dictionary dictObj) + { + return dictObj; + } + + if (customFields is IDictionary genericDict) + { + var result = new Dictionary(); + foreach (DictionaryEntry entry in genericDict) + { + result[entry.Key?.ToString() ?? string.Empty] = entry.Value ?? string.Empty; + } + return result; + } + + return new Dictionary(); + } + + /// + /// Executes an async operation synchronously and handles errors. + /// + /// The return type of the operation. + /// The async operation to execute. + /// The error ID for error reporting. + /// The result of the operation, or default if an error occurred. + protected T? ExecuteAsync(Func> operation, string errorId) + { + try + { + return operation().GetAwaiter().GetResult(); + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, errorId, ErrorCategory.InvalidOperation, null)); + return default; + } + } + + /// + /// Executes an async operation synchronously and handles errors. + /// + /// The async operation to execute. + /// The error ID for error reporting. + protected void ExecuteAsync(Func operation, string errorId) + { + try + { + operation().GetAwaiter().GetResult(); + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, errorId, ErrorCategory.InvalidOperation, null)); + } + } +} diff --git a/classlib/IsExternalInit.cs b/classlib/IsExternalInit.cs new file mode 100644 index 0000000..85ba17f --- /dev/null +++ b/classlib/IsExternalInit.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// This file provides the IsExternalInit type required for using C# 9 records +// in projects targeting .NET Standard 2.1 or earlier. + +#if !NET5_0_OR_GREATER + +namespace System.Runtime.CompilerServices +{ + using System.ComponentModel; + + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class IsExternalInit + { + } +} + +#endif diff --git a/classlib/enum/SessionStatus.cs b/classlib/enum/SessionStatus.cs new file mode 100644 index 0000000..0c9c73c --- /dev/null +++ b/classlib/enum/SessionStatus.cs @@ -0,0 +1,22 @@ +namespace PS.IPAM; + +/// +/// Represents the current status of an API session. +/// +public enum SessionStatus +{ + /// + /// No session exists or no token is available. + /// + NoSession, + + /// + /// The session token has expired. + /// + Expired, + + /// + /// The session is valid and ready for use. + /// + Valid +}