Skip to content

Latest commit

 

History

History
703 lines (482 loc) · 18.8 KB

File metadata and controls

703 lines (482 loc) · 18.8 KB

PowerCSharp.Extensions API Documentation

This document provides comprehensive API documentation for all extension methods in the PowerCSharp.Extensions package.

Table of Contents

Collections

IListExtensions

RemoveAll

Removes all elements from an IList that satisfy the specified condition.

public static int RemoveAll<T>(this IList<T> list, Predicate<T> match)

Parameters:

  • list: The IList to remove elements from
  • match: The predicate condition to match elements for removal

Returns: The number of elements removed from the list

Example:

var list = new List<string> { "keep", "remove", "keep", "remove" };
int removed = list.RemoveAll(x => x == "remove"); // Returns 2

Configuration

ConfigurationExtensions

GetOptions

Gets options from IConfiguration object using the specified configuration section path.

public static TOptions GetOptions<TOptions>(this IConfiguration configuration, string sectionPath)
    where TOptions : class, IAppOptions

Parameters:

  • configuration: The IConfiguration object to read from
  • sectionPath: The configuration section path to use

Returns: The configured options object

Exceptions:

  • ArgumentNullException: When configuration is null
  • ArgumentException: When sectionPath is null or whitespace
  • InvalidOperationException: When binding fails

Example:

var options = configuration.GetOptions<MyAppOptions>("MyApp");

HTTP & Network

HttpStatusCodeExtensions

IsSuccessful

Checks if the HTTP status code is successful (2xx range).

public static bool IsSuccessful(this HttpStatusCode statusCode)
public static bool IsSuccessful(this int statusCode)

IsClientError

Checks if the HTTP status code is a client error (4xx range).

public static bool IsClientError(this HttpStatusCode statusCode)
public static bool IsClientError(this int statusCode)

IsServerError

Checks if the HTTP status code is a server error (5xx range).

public static bool IsServerError(this HttpStatusCode statusCode)
public static bool IsServerError(this int statusCode)

IsError

Checks if the HTTP status code is an error (4xx or 5xx range).

public static bool IsError(this HttpStatusCode statusCode)
public static bool IsError(this int statusCode)

IsRedirect

Checks if the HTTP status code is in the redirect category (3xx range).

public static bool IsRedirect(this HttpStatusCode statusCode)
public static bool IsRedirect(this int statusCode)

IsCaching

Checks if the HTTP status code indicates caching (NotModified).

public static bool IsCaching(this HttpStatusCode statusCode)

Example:

HttpStatusCode status = HttpStatusCode.OK;
bool success = status.IsSuccessful(); // true
bool clientError = status.IsClientError(); // false

UriExtensions

AddParameter

Adds the specified parameter to the query string of the URI.

public static Uri AddParameter(this Uri url, string parameterName, string parameterValue)

Parameters:

  • url: The base URI to add the parameter to
  • parameterName: The name of the parameter to add
  • parameterValue: The value for the parameter to add

Returns: A new URI with the added parameter in the query string

Example:

Uri uri = new Uri("https://example.com");
Uri withParam = uri.AddParameter("search", "test");
// Result: https://example.com?search=test

HttpRequestMessageExtensions

Clone

Creates a deep clone of the HttpRequestMessage including headers, content, and properties.

public static HttpRequestMessage Clone(this HttpRequestMessage original)

CloneAsync

Creates a deep clone of the HttpRequestMessage asynchronously.

public static Task<HttpRequestMessage> CloneAsync(this HttpRequestMessage original, CancellationToken cancellationToken = default)

Parameters:

  • original: The original HttpRequestMessage to clone
  • cancellationToken: A cancellation token to cancel the operation

Returns: A new HttpRequestMessage instance with all headers, content, and properties copied

Example:

using var request = new HttpRequestMessage(HttpMethod.Get, "https://api.example.com");
var clonedRequest = request.Clone();
var clonedAsync = await request.CloneAsync();

JSON & XML

JsonExtensions

Get (string)

Looks for a property with the specified name in the current JSON element.

public static JsonElement? Get(this JsonElement element, string name)

Get (int)

Looks for a property by index in the current JSON array element.

public static JsonElement? Get(this JsonElement element, int index)

Parameters:

  • element: The JSON element to search within
  • name: The name of the property to find
  • index: The zero-based index of the element to retrieve

Returns: The JsonElement value if found and valid; otherwise, null

Example:

JsonElement element = JsonDocument.Parse("{\"name\":\"John\"}").RootElement;
var name = element.Get("name"); // JsonElement with value "John"

JsonElementExtensions

TryGetPropertyCaseInsensitive

Looks for a property with the specified name using case-insensitive comparison.

public static bool TryGetPropertyCaseInsensitive(this JsonElement element, string propertyName, out JsonElement value)

Parameters:

  • element: The JSON element to search within
  • propertyName: The name of the property to find (case-insensitive)
  • value: When this method returns, contains the JsonElement value if the property was found

Returns: True if the property exists; otherwise, false

Example:

bool found = element.TryGetPropertyCaseInsensitive("NAME", out var value);

XmlExtensions

Flatten

Gets the XElement transformed into a Dictionary representation.

public static Dictionary<string, object> Flatten(this XElement xmlElement)

Parameters:

  • xmlElement: The XML element to flatten

Returns: A dictionary representation of the XML element with attributes and nested elements

Example:

XElement xml = XElement.Parse("<root><child>value</child></root>");
var dict = xml.Flatten(); // Dictionary with XML structure

LINQ & Dynamic Queries

DynamicExpressionExtensions

GetExpressionDelegate

Parses a LINQ expression string into a compiled predicate function.

public static Func<T, bool> GetExpressionDelegate<T>(this string stringExpression)

GetOrderDelegates

Parses a LINQ expression string into a list of ordering delegates.

public static List<(Func<TSource, object>, bool)> GetOrderDelegates<TSource>(this string stringExpression)

Parameters:

  • stringExpression: The string expression to parse

Returns: A predicate function or list of ordering delegates

Example:

string expression = "Age > 18 && Name.Contains('John')";
var predicate = expression.GetExpressionDelegate<Person>();

string orderExpression = "Name DESC, Age ASC";
var orderDelegates = orderExpression.GetOrderDelegates<Person>();

IEnumerableExtensions

Filter

Filters a sequence of values based on a dynamic filter provider.

public static IEnumerable<TSource> Filter<TSource>(this IEnumerable<TSource> source, IDynamicFilterProvider<TSource>? filterProvider)

Order

Sorts the elements of a sequence in ascending or descending order based on a dynamic order provider.

public static IEnumerable<TSource> Order<TSource>(this IEnumerable<TSource> source, IDynamicOrderProvider<TSource>? orderProvider)

Parameters:

  • source: The source sequence to filter/sort
  • filterProvider: The dynamic filter provider containing filter criteria
  • orderProvider: The dynamic order provider containing ordering criteria

Returns: An IEnumerable with elements filtered or sorted

Example:

var filterProvider = new DynamicFilterProvider<Person>();
var orderProvider = new DynamicOrderProvider<Person>();
var filtered = people.Filter(filterProvider);
var ordered = people.Order(orderProvider);

Objects & Types

GenericExtensions

FromHierarchy

Processes a structure hierarchically using the provided next item function and continuation condition.

public static IEnumerable<TSource> FromHierarchy<TSource>(this TSource source, Func<TSource, TSource> nextItem, Func<TSource, bool> canContinue)
public static IEnumerable<TSource> FromHierarchy<TSource>(this TSource source, Func<TSource, TSource> nextItem)
    where TSource : class

CopyPropertiesTo<TSource, TDestination>

Copies all matching properties by name and type from the source object to the destination object.

public static void CopyPropertiesTo<TSource, TDestination>(this TSource source, TDestination destination)
    where TSource : class
    where TDestination : class

Example:

var person = new Person { Name = "John", Age = 30 };
var copy = new Person();
person.CopyPropertiesTo(copy); // Copies matching properties

ObjectExtensions

ThrowOnNull

Throws an ArgumentNullException if the value is null.

public static T ThrowOnNull<T>(this T? value)
    where T : class

TryGetBool

Attempts to convert various types of input into a boolean value.

public static bool TryGetBool(this object value, out bool result)

Map

Maps properties from the source object to a new destination object of type TDATA.

public static TDATA? Map<TDATA>(this object oldObject)
    where TDATA : class, new()

Example:

string text = "test";
text.ThrowOnNull(); // Throws if null

bool isTrue = "true".TryGetBool(out bool result); // result = true, isTrue = true

GenericTypeExtensions

IsDefault

Check if the value is equal to its default value.

public static bool IsDefault<T>(this T value)

GetGenericTypeName

Returns the name of the generic type of the object, including generic parameters.

public static string GetGenericTypeName(this object @object)

Example:

bool isDefault = default(int).IsDefault(); // true
string typeName = typeof(List<string>).GetGenericTypeName(); // "List<String>"

TypeExtensions

GetConcreteType

Returns the concrete Type that implements the specified interface type.

public static Type? GetConcreteType(this Type interfaceType)

Example:

Type concreteType = typeof(IMyInterface).GetConcreteType();

Streams

StreamExtensions

CloneAsync

Asynchronously clones the content of this stream to another stream.

public static Task CloneAsync(this Stream stream, Stream? destination)

Parameters:

  • stream: The source stream to clone
  • destination: The destination stream. If null, a new MemoryStream will be created

Example:

using var originalStream = new MemoryStream(Encoding.UTF8.GetBytes("test data"));
using var destinationStream = new MemoryStream();
await originalStream.CloneAsync(destinationStream);

Strings

StringExtensions

Mid

Gets the middle part of a string starting from the specified index.

public static string Mid(this string text, int start)

FirstCharToLowerCase

Gets the string with the first character converted to lowercase.

public static string? FirstCharToLowerCase(this string? input)

ToCamelCase

Converts the string to camel case format.

public static string ToCamelCase(this string input)

NormalizeKey

Normalizes a string to be a valid JSON key.

public static string NormalizeKey(this string input)

AsAscii

Strips non-ASCII characters from the string.

public static string AsAscii(this string input)

IsValidUrl

Returns true if the string is a valid absolute HTTP or HTTPS URL.

public static bool IsValidUrl(this string input)

Example:

string camel = "HelloWorld".ToCamelCase(); // "helloWorld"
string firstLower = text.FirstCharToLowerCase(); // "hello world"
string normalized = "User Name".NormalizeKey(); // "userName"
bool isValid = "https://example.com".IsValidUrl(); // true

Hash Extensions

HashExtensions

ComputeHash

Computes a short hash string from any object by serializing it to JSON and applying SHA256 hashing.

public static string ComputeHash(this object obj)

Parameters:

  • obj: The object to hash. Can be any serializable type or null.

Returns: A 16-character hexadecimal hash string representing the object's content. Returns "null" if the input object is null. Returns a fallback hash if serialization fails, incorporating the type name and error information.

Exceptions: None - handles serialization failures gracefully.

Example:

var person = new { Name = "John", Age = 30, Email = "john@example.com" };
string hash = person.ComputeHash(); // "A1B2C3D4E5F67890"

var complexObj = new Order 
{ 
    Id = 123, 
    Customer = new Customer { Name = "Alice" }, 
    Items = new List<Item> { new Item { Name = "Product1" } }
};
string orderHash = complexObj.ComputeHash(); // Consistent hash for caching/identification

Notes:

  • Uses JSON serialization with stable, deterministic options
  • Handles circular references and very large nested objects
  • Provides fallback hashing for non-serializable objects
  • Optimized for performance with minimal allocations

Path Extensions

PathExtensions

CombineAndValidate

Combines path segments and validates the result to prevent directory traversal attacks (CWE-73).

public static string CombineAndValidate(string basePath, string relativePath)
public static string CombineAndValidate(string basePath, params string[] paths)

Parameters:

  • basePath: The base directory path that serves as the security boundary
  • relativePath: The relative path to combine with the base path
  • paths: Additional path segments to combine (overload)

Returns: The validated absolute path that is guaranteed to be within the base directory.

Exceptions:

  • ArgumentNullException: Thrown when basePath or relativePath/paths is null
  • ArgumentException: Thrown when basePath is empty or no paths provided
  • SecurityException: Thrown when the combined path attempts directory traversal

Example:

string basePath = "/var/www/uploads";
string userFile = "../../etc/passwd"; // Malicious attempt

// This will throw SecurityException due to directory traversal attempt
string safePath = PathExtensions.CombineAndValidate(basePath, userFile);

// Safe usage with valid relative paths
string validPath = PathExtensions.CombineAndValidate(basePath, "images/photo.jpg");
// Returns: "/var/www/uploads/images/photo.jpg"

// Multiple path segments
string multiPath = PathExtensions.CombineAndValidate(basePath, "documents", "2023", "report.pdf");
// Returns: "/var/www/uploads/documents/2023/report.pdf"

Security Features:

  • Implements Veracode CWE-73 remediation pattern
  • Canonicalizes paths to resolve ".", "..", "~" directives
  • Validates path stays within base directory
  • Logs security events for monitoring
  • Provides consistent error handling

Interfaces

All interfaces are centralized in PowerCSharp.Core to maintain proper architectural separation and provide a unified foundation for the entire PowerCSharp ecosystem.

IDynamicFilterProvider

Namespace: PowerCSharp.Core.Interfaces.Extensions.Linq

Implement a Service Provider for dynamically filtering of the type T using Dynamic Expressions.

public interface IDynamicFilterProvider<T>
{
    void SetFilter(Func<T, bool> filter);
    Func<T, bool> GetFilter();
}

IDynamicOrderProvider

Namespace: PowerCSharp.Core.Interfaces.Extensions.Linq

Implement a Service Provider for dynamically ordering of the type T using Dynamic Expressions.

public interface IDynamicOrderProvider<T>
{
    void SetOrderDelegates(List<(Func<T, object>, bool)> delegates);
    List<(Func<T, object>, bool)> GetOrderDelegates();
}

IAppOptions

Namespace: PowerCSharp.Core.Interfaces.Extensions.Configuration

Represents the interface for application options.

public interface IAppOptions
{
    string ConfigSectionPath { get; }
}

Interface Architecture

The interface organization follows a clear hierarchical structure:

  • PowerCSharp.Core.Interfaces - Root namespace for all interfaces
    • Extensions.Configuration - Configuration-related interfaces
    • Extensions.Linq - LINQ and dynamic query interfaces
    • Models - Model classes (reserved for future use)

This centralization ensures:

  • Single source of truth for contracts and abstractions
  • Consistent namespace organization
  • Easy dependency management across packages
  • Clear architectural boundaries

Framework Support

  • .NET 8.0 - Full support with all features
  • .NET Standard 2.0 - Compatible with .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5+

Dependencies

The PowerCSharp.Extensions package requires the following NuGet packages:

  • System.Linq.Dynamic.Core - For dynamic LINQ expression parsing
  • Microsoft.AspNetCore.WebUtilities - For URL query string manipulation
  • Microsoft.Extensions.Configuration.Abstractions - For configuration support
  • Microsoft.Extensions.Configuration.Binder - For configuration binding
  • System.Text.Json - For JSON processing

Thread Safety

All extension methods in PowerCSharp.Extensions are designed to be thread-safe when used with immutable data structures. For mutable collections, proper synchronization should be maintained by the calling code.

Performance Considerations

  • Dynamic LINQ extensions involve runtime compilation and may have performance overhead compared to compiled LINQ queries
  • String manipulation methods create new string instances and should be used judiciously in performance-critical code
  • Stream cloning creates copies of stream data and should be used with awareness of memory implications

Error Handling

All extension methods include comprehensive null checking and graceful error handling:

  • ArgumentNullException is thrown for null parameters where applicable
  • InvalidOperationException is thrown for invalid operations
  • Methods return default values or empty collections when appropriate rather than throwing exceptions

For more detailed information about specific methods, refer to the XML documentation included in the source code.